home *** CD-ROM | disk | FTP | other *** search
- ;* INTERPRT.ASM
- ;************************************************************************
- ;* *
- ;* PC Scheme/Geneva 4.00 Borland TASM code *
- ;* *
- ;* (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- ;* (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* The main VM interpreter loop *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Created by: John Jensen Date: 1985 *
- ;* Revision history: *
- ;* - 11 Feb 86: Replaced support for even? and odd? to reduce code *
- ;* size and to update error messages. *
- ;* Improved error handling for divide, quotient, and *
- ;* remainder. *
- ;* Fixed divide by zero error in Remainder function *
- ;* - 7 Jan 87: added random I/O - dbs *
- ;* - 10 Feb 87: added new opcode (186) for read-line - tc *
- ;* - 8 Mar 87: variable-length opcodes - rb *
- ;* - 16 Mar 87: Added dos-err entry point to detect Dos I/O errors. *
- ;* - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- ;* *
- ;* ``In nomine omnipotentii dei'' *
- ;************************************************************************
- IDEAL
- %PAGESIZE 60, 132
- MODEL small
- LOCALS @@
-
- INCLUDE "scheme.ash"
-
- SEGMENT NILPAGE PARA PUBLIC 'FAR_DATA'
- ENDS NILPAGE
-
- DATASEG
- ; Primary opcode lookup table
- op_table DW copy ; 000- load dest,src
- DW ld_const ; 001- ld-const dest,constant-number (byte)
- DW ld_imm ; 002- ld-imm dest,immed-value (byte)
- DW ld_nil ; 003- ld-nil dest
- DW ld_local ; 004- ld-local dest,entry-number (byte)
- DW ld_lex ; 005- ld-lex dest,entry-no,delta-level
- DW ld_env ; 006- ld-env R(dest),C(sym)
- DW ld_globl ; 007- ld-global dest,constant-number (byte)
-
- DW ld_fluid ; 008- ld-fluid dest,constant-number (byte)
- DW ld_off_s ; 009- ld-vec-s vect,offset (byte)
- DW ld_off_l ; 010- ld-vec-l vect,offset (word)
- DW ld_off_r ; 011- ld-vec-r vect,offset (reg)
- DW st_local ; 012- st-local src,entry-number (byte)
- DW st_lex ; 013- st-lex src,entry-no,delta-level
- DW st_env ; 014- st-env R(val),C(sym)
- DW st_globl ; 015- st-global src,constant-number (byte)
-
- DW st_fluid ; 016- st-fluid src,constant-number (byte)
- DW st_off_s ; 017- st-vec-s vect,offset (byte),src
- DW st_off_l ; 018- st-vec-l vect,offset (word),src
- DW st_off_r ; 019- st-vec-r vect,offset (reg),src
- DW set_car ; 020- set-car! dest,src
- DW set_cdr ; 021- set-cdr! dest,src
- DW recompil ; 022- (unused) formerly set-ref!
- DW recompil ; 023- (unused) formerly swap-ref!
-
- DW spop ; 024- pop dest
- DW spush ; 025- push src
- DW sdrop ; 026- drop count (unsigned byte)
- DW ld_globr ; 027- ld-global-r dest,sym
- DW recompil ; 028- (unused- formerly push-heap)
- DW bind_fl ; 029- bind-fl const,src
- DW unbind_f ; 030- unbind_fl count (byte)
- DW define ; 031- define! src,const
-
- DW jmp_shrt ; 032- jmp_s label (byte)
- DW jmp_long ; 033- jmp_l label (word)
- DW j_nil_s ; 034- jnil_s reg,label (byte)
- DW j_nil_l ; 035- jnil_l reg,label (word)
- DW j_nnil_s ; 036- jnnil_s reg,label (byte)
- DW j_nnil_l ; 037- jnnil_l reg,label (word)
- DW j_atm_s ; 038- jatom_s reg,label (byte)
- DW j_atm_l ; 039- jatom_l reg,label (word)
-
- DW j_natm_s ; 040- jnatom_s reg,label (byte)
- DW j_natm_l ; 041- jnatom_l reg,label (word)
- DW j_eq_s ; 042- jeq_s reg,label (byte)
- DW j_eq_l ; 043- jeq_l reg,label (word)
- DW j_neq_s ; 044- jneq_s reg,label (byte)
- DW j_neq_l ; 045- jneq_l reg,label (word)
- DW recompil ; 046- (unused) formerly deref
- DW recompil ; 047- (unused) formerly ref
-
- DW call_lcl ; 048- call lbl,delta-level,delta-heap
- DW call_ltr ; 049- call-tr lbl,delta-level,delta-heap
- DW call_cc ; 050- call/cc lbl,delta-level,delta-heap
- DW cl_cctr ; 051- call/cc-tr lbl delta-level,delta-heap
- DW call_clo ; 052- call-cl reg,number-args
- DW call_ctr ; 053- call-cl-tr reg,number-args
- DW clcc_c ; 054- call/cc-cl reg
- DW clcc_ctr ; 055- call/cc-cl-tr reg
-
- DW apply ; 056- apply-cl reg,arg
- DW apply_tr ; 057- apply-cl-tr reg,arg
- DW execute ; 058- execute reg
- DW s_exit ; 059- exit
- DW cr_close ; 060- close dest,label,number-args
- DW drop_env ; 061- drop-env count
- DW hash_env ; 062- make-hashed-environment
- DW ld_fl_r ; 063- ld-fluid-r dest,sym
-
- DW ld_car ; 064- car dest,src
- DW ld_cdr ; 065- cdr dest,src
- DW ld_caar ; 066- caar dest,src
- DW ld_cadr ; 067- cadr dest,src
- DW ld_cdar ; 068- cdar dest,src
- DW ld_cddr ; 069- cddr dest,src
- DW ld_caaar ; 070- caaar dest,src
- DW ld_caadr ; 071- caadr dest,src
-
- DW ld_cadar ; 072- cadar dest,src
- DW ld_caddr ; 073- caddr dest,src
- DW ld_cdaar ; 074- cdaar dest,src
- DW ld_cdadr ; 075- cdadr dest,src
- DW ld_cddar ; 076- cddar dest,src
- DW ld_cdddr ; 077- cdddr dest,src
- DW ld_caddd ; 078- cadddr dest,src
- DW s_cons ; 079- cons dest,car,cdr
-
- DW addproc ; 080- add dest,src
- DW addi ; 081- add-imm dest,imm (signed byte)
- DW subproc ; 082- sub dest,src
- DW mulproc ; 083- mul dest,src
- DW muli ; 084- mul-imm dest,imm (signed byte)
- DW divproc ; 085- div dest,src
- DW divi ; 086- div-imm dest,imm (signed byte)
- DW quotient ; 087- quotient dest,src **integers only**
-
- DW remainder ; 088- remainder dest,src
- DW ld_car1 ; 089- %car src=dest
- DW ld_cdr1 ; 090- %cdr src=dest
- DW random ; 091- %random dest
- DW lt_p ; 092- < dest,src
- DW le_p ; 093- <= dest,src
- DW eq_n ; 094- = dest,src
- DW gt_p ; 095- > dest,src
-
- DW ge_p ; 096- >= dest,src
- DW ne_p ; 097- <> dest,src
- DW maximum ; 098- max dest,src
- DW minimum ; 099- min dest,src
- DW eq_p ; 100- eq? dest,src
- DW eqv_p ; 101- eqv? dest,src
- DW equal_p ; 102- equal? dest,src
- DW memq ; 103- memq dest,src
-
- DW memv ; 104- memv dest,src
- DW member ; 105- member dest,src
- DW reverseb ; 106- reverse! list
- DW not_yet ; 107- reverse list
- DW assq ; 108- assq obj,list
- DW assv ; 109- assv obj,list
- DW assoc ; 110- assoc obj,list
- DW s_list ; 111- list obj
-
- DW appendb ; 112- append! list,obj
- DW append ; 113- append list,obj
- DW not_yet ; 114- delq! obj,list
- DW not_yet ; 115- delete! obj,list
- DW getprop ; 116- get-prop name,prop
- DW putprop ; 117- put-prop name,val,prop
- DW proplist ; 118- proplist name
- DW remprop ; 119- remprop name,prop
-
- DW list2 ; 120- list2 dest=src1,src2
- DW not_yet ; 121- list-ref dest=src1,src2
- DW l_tail ; 122- list-tail dest,count
- DW divide ; 123- divide dest,src **integers only**
- DW modulo ; 124- modulo dest, src
- DW b_xor ; 125- bitwise-xor dest=src1,src2
- DW b_and ; 126- bitwise-and dest=src1,src2
- DW b_or ; 127- bitwise-or dest=src1,src2
-
- ; Note: the second half of the opcodes are "second class" opcodes,
- ; in that TIPC register bh will not be zero at the entry to the
- ; support routine. For the following instructions, bh will
- ; contain the value one (1).
-
- DW atom_p ; 128- atom? dest
- DW closur_p ; 129- closure? dest
- DW code_p ; 130- code? dest
- DW contin_p ; 131- continuation? dest
- DW even_p ; 132- even? dest
- DW float_p ; 133- float? dest
- DW fluid_p ; 134- fluid-bound? dest
- DW integr_p ; 135- integer? dest
-
- DW null_p ; 136- null? dest
- DW number_p ; 137- number? dest
- DW odd_p ; 138- odd? dest
- DW pair_p ; 139- pair? dest
- DW port_p ; 140- port? dest
- DW proc_p ; 141- proc? dest
- DW inline_p ; 142- inline? dest
- DW string_p ; 143- string? dest
-
- DW symbol_p ; 144- symbol? dest
- DW vector_p ; 145- vector? dest
- DW eq_z_p ; 146- zero? dest
- DW lt_z_p ; 147- negative? dest
- DW gt_z_p ; 148- positive? dest
- DW sabs ; 149- abs dest
- DW float ; 150- float dest
- DW minus ; 151- minus dest
-
- DW sfloor ; 152- floor dest
- DW sceiling ; 153- ceiling dest
- DW struncat ; 154- truncate dest
- DW sround ; 155- round dest
- DW char_p ; 156- char? dest
- DW env_p ; 157- env? dest
- DW not_op
- DW not_op
-
- DW asc_char ; 160- asc->char reg
- DW char_asc ; 161- char->asc reg
- DW str_str ; 162- %str-str str,start,end,str,dir,case
- DW not_op
- DW not_op
- DW slength ; 165- length list
- DW lst_pair ; 166- last-pair list
- DW substring ; 167- substr str,pos,len
-
- DW vec_allo ; 168- alloc-vec dest
- DW vec_size ; 169- vect-length dest
- DW vec_fill ; 170- vect-fill vect,val
- DW not_yet ; 171- make-pack-vect len,bits/elem,signed?
- DW s_disply ; 172- %substr-display str,start,end,row,wind
- DW unread_char ; 173- unread-char port
- DW set_tim ; 174- %start-timer src=ticks
- DW rst_tim ; 175- %stop-timer dest=ticks remaining
-
- DW p_open ; 176- open-port filename,mode
- DW p_close ; 177- close-port port
- DW spprin1 ; 178- prin1 obj,port
- DW spprinc ; 179- princ obj,port
- DW spprint ; 180- print obj,port
- DW spnewlin ; 181- newline port
- DW push_hist ; 182- %push-history
- DW get_hist ; 183- %get-history
-
- DW prt_len ; 184- print-length obj
- DW clr_hist ; 185- clear-history
- DW srd_line ; 186- read-line dest=src (src={port})
- DW srd_atom ; 187- read-atom dest=src (src={port})
- DW read_char ; 188- read-char dest=src
- DW trns_chg ; 189- %transcript src
- DW rd_char_rdy ; 190- read-char-ready? dest=src
- DW sfasl ; 191- fasl string
-
- DW ch_eq_p ; 192- char= char1,char2
- DW ch_eq_ci ; 193- char-equal? char1,char2
- DW ch_lt_p ; 194- char< char1,char2
- DW ch_lt_ci ; 195- char-less? char1,char2
- DW ch_up ; 196- char-upcase char
- DW ch_down ; 197- char-downcase char
- DW str_lng ; 198- string-length string
- DW st_ref ; 199- string-ref string,index
-
- DW st_set ; 200- string-set! string,index,char
- DW make_str ; 201- make-string length,char
- DW str_fill ; 202- string-fill! string,char
- DW str2sym ; 203- string->symbol string
- DW str2usym ; 204- string->uninterned-symbol string
- DW sym2str ; 205- symbol->string symbol
- DW srch_nx ; 206- srch-next-char str,start,end,charset
- DW srch_pr ; 207- srch-prev-char str,start,end,charset
-
- DW make_win ; 208- make-window label
- DW set_w_at ; 209- set-wind-attr wind,attr,value
- DW get_wind ; 210- get-wind-attr wind,attr
- DW clr_wind ; 211- clear-window wind
- DW save_win ; 212- save-window wind
- DW rest_win ; 213- restore-wind wind
- DW s_append ; 214- %str-append R(d=s1),R(s2),...,R(s7)
- DW sgraph ; 215- %graphics len, R(d=s1),R(s2),...
-
- DW sreify ; 216- %reify R(s1=d),R(s2) ;obj,indx
- DW mk_env ; 217- mk-env R(d)
- DW env_par ; 218- env-par R(d=s1) ; s1=env
- DW env_lu ; 219- env-lu R(d=s1),R(s2) ; sym,env
- DW def_env ; 220- def-env R(d=s1),R(s2),R(s3) sve
- DW push_env ; 221- push-env C(s1) ; s1=list of syms
- DW drop_env ; 222- drop-env
- DW ld_env ; 223- ld-env R(d),C(s1) ; s1=symbol
-
- DW st_env ; 224- st-env R(d=s1),C(s2) ; val,sym
- DW set_gnv ; 225- set-glob-env! R(s1) ; s1=env
- DW sreifyb ; 226- %reify! R(s1),R(s2),R(s3);o,i,v
- DW obj_hash ; 227- object-hash R(d=s1)
- DW obj_unhs ; 228- object-unhash R(d=s1)
- DW reify_s ; 229- reify-stack R(d=s1)
- DW reify_sb ; 220- reify-stack! R(s1),R(s2)
- DW sfpos ; 231- set-file-position!
-
- DW s_esc ; 232- %esc len, R(d=s1),R(s2),...
- DW smouse ; 233- %mouse len, R(d=s1),R(s2),...
- DW recompil ; 234- unused (formerly %esc3)
- DW recompil ; 235- unused (formerly %esc4)
- DW recompil ; 236- unused (formerly %esc5)
- DW recompil ; 237- unused (formerly %esc6)
- DW recompil ; 238- unused (formerly %esc7)
- DW recompil ; 239- unused (formerly %xesc)
-
- DW port_make ; 240- make-port R(d=type), R(srce)
- DW port_get ; 241- %port-get-attribute R(d=port), R(s1)
- DW port_set ; 242- %port-set-attribute! R(d=port), R(s1), R(s2)
- DW port_char ; 243- %read-char
- DW port_line ; 244- %read-line
- DW port_ready ; 245- %char-ready?
- DW port_peek ; 246- %peek-char
- DW sgc2 ; 247- gc-with-compaction
-
- DW exit_op ; 248- halt (return to MS-DOS)
- DW gc ; 249- %garbage-collect
- DW recompil ; 250- unused (formerly %internal-time)
- DW reset ; 251- reset
- DW s_reset ; 252- scheme-reset
- DW clr_regs ; 253- %clear-registers
- DW not_op ; 254- (reserved for escape)
- DW debug_op ; 255- %begin-debug
-
- UDATASEG
- reset_bp DW ? ; initial value of bp for reset purposes
- CODESEG
-
- ;************************************************************************
- ;* Macro support for out-of-line calls to Borland C *
- ;************************************************************************
- PROC get1parm NEAR
- xor ax, ax
- get1op
- add ax, OFFSET regs ; compute address of register
- save <si>
- ret
- ENDP get1parm
-
- PROC get2parm NEAR
- get2op
- xor bx, bx
- xchg bl, ah
- add bx, OFFSET regs ; compute address of register
- add ax, OFFSET regs
- save <si>
- ret
- ENDP get2parm
-
- PROC get3parm NEAR
- xor cx, cx
- get1op
- mov cx, ax
- get2op
- xor bx, bx
- xchg bl, ah
- add cx, OFFSET regs ; and compute register address
- add bx, OFFSET regs ; compute address of register
- add ax, OFFSET regs
- save <si>
- ret
- ENDP get3parm
-
- PROC get4parm NEAR
- get2op
- xor dx, dx
- xchg dl, ah ; copy 2nd operand register number
- mov cx, ax ; copy 1st operand register number
- get2op
- xor bx, bx
- xchg bl, ah ; copy 4th operand register number
- add dx, OFFSET regs
- add cx, OFFSET regs
- add bx, OFFSET regs ; compute address of register
- add ax, OFFSET regs
- save <si>
- ret
- ENDP get4parm
-
- ;************************************************************************
- ;* Common Support for EVEN?/ODD? *
- ;* *
- ;* Input Parameters: es:[si] - pointer to even?/odd? instruction's *
- ;* operand. *
- ;* dx ------ text address for "EVEN?" or "ODD?" to *
- ;* be used to create an error message if *
- ;* an error is detected. *
- ;* *
- ;* Output Parameters: Zero Flag (condition code) - 0 => even number *
- ;* 1 => odd number *
- ;* *
- ;* Note: If an invalid operand is detected, this routine exits *
- ;* to the Scheme debugger. *
- ;************************************************************************
- PROC eo_which NEAR
- get1op
- mov bx, ax ; copy register number to bx
- add bx, OFFSET regs
- cmp [(REG bx).bpage], SPECFIX*2
- jne @@notfix
- test [(REG bx).disp], 1
- ret
- @@notfix:
- mov di, [(REG bx).page]
- cmp [ptype+di], BIGTYPE ; is operand a bignum?
- jne @@notbig
- push es ; saves es
- ldpage es, di
- mov di, [(REG bx).disp]
- test [BYTE (BIGDEF es:di).data.lsw], 1 ; test LSB of bignum
- pop es ; restore es register
- ret
- @@notbig:
- mov ax, 1
- call set_src_error C, dx, ax, bx
- pop ax ; drop the caller's address
- jmp sch_err
- ENDP eo_which
-
- ;************************************************************************
- ;* Entry point to force debug mode prior to next VM instruction *
- ;************************************************************************
- PROC C force_debug FAR
- IFDEF VMDEBUG
- mov ax, [cs:$$sm$debug]
- mov [cs:$$sm$entry], ax
- ENDIF
- ret
- ENDP force_debug
-
- ;************************************************************************
- ;* Entry point to force a timeout prior to next VM instruction. *
- ;* This will be called from the tick routine in STIMER.ASM. *
- ;************************************************************************
- PROC C force_timeout FAR
- mov ax, [cs:$$sm$timer]
- xchg [cs:$$sm$entry], ax
- mov [cs:reset_timer], ax
- ret
- ENDP force_timeout
-
- ;************************************************************************
- ;* Interrupt handler for mouse *
- ;************************************************************************
- UDATASEG
- STRUC MOUSESTATE
- flags DW ?
- state DW ?
- x DW ?
- y DW ?
- x_mickeys DW ?
- y_mickeys DW ?
- time DD ?
- ENDS
- mstate MOUSESTATE 6 dup (?) ; provide for 6 events,
- DATASEG ; or a triple-click
- mstptr DW mstate
- CODESEG
- PROC C mouse_handler FAR
- push ds
- push bx ; save bx, an useful pointer
- mov bx, DGROUP ; and state-holder
- mov ds, bx
-
- cli ; don't allow reentrance here
- mov bx, [mstptr]
- cmp bx, OFFSET mstate + 6 * (SIZE MOUSESTATE)
- jae @@abort ; sorry, no room left
- add [mstptr], SIZE MOUSESTATE
- sti
- mov [(MOUSESTATE bx).flags], ax
- mov [(MOUSESTATE bx).x], cx
- mov [(MOUSESTATE bx).y], dx
- mov [(MOUSESTATE bx).x_mickeys], si
- mov [(MOUSESTATE bx).y_mickeys], di
- pop si ; restore mouse state
- mov [(MOUSESTATE bx).state], si
- push bx
- call clock C
- pop bx
- mov [WORD LOW (MOUSESTATE bx).time], ax
- mov [WORD HIGH (MOUSESTATE bx).time], dx
-
- mov ax, [cs:$$sm$mouse]
- xchg [cs:$$sm$entry], ax
- cmp ax, [cs:$$sm$mouse] ; did we already interrupt?
- je @@alreadydone
- mov [cs:reset_mouse], ax
- @@alreadydone:
- pop ds
- ret
- @@abort:
- sti
- pop bx
- pop ds
- ret
- ENDP
-
- ;************************************************************************
- ;* Entry point to process shift-break prior to next VM instruction *
- ;************************************************************************
- reset_sb DW 0
- PROC shft_brk FAR
- push es si di ax
- mov ax, @data
- mov es, ax
- inc [BYTE es:s_break]
- cmp [WORD es:vm_debug], 0
- jz @@notVMmode
- call force_debug C ; if we're in VM_debug mode, jump
- jmp @@abort
- @@notVMmode:
- mov ax, [cs:$$sm$break] ; else, force a trap to the debugger
- cmp ax, [cs:$$sm$entry] ; Shift-Brk already depressed?
- je @@abort
- xchg [cs:$$sm$entry], ax ; else enter scheme debugger on
- mov [cs:reset_sb], ax ; next vm instruction
- @@abort:
- pop ax di si es
- ret
- ENDP shft_brk
-
- PROC run FAR
- mov ax, [cs:$$sm$go] ; modify interpreter loop to disable
- mov [cs:$$sm$entry], ax ; instruction level trace capability
- ; jmp interp ; fall through
- ENDP run
-
- ;************************************************************************
- ;* Scheme VM interpreter entry point *
- ;************************************************************************
- ;* If you change the USES registers section of proc header, update the *
- ;* following constant (used for stack restore after any serious error) *
- ;************************************************************************
- USESSIZE EQU 2 * 2
- PROC C interp FAR USES si di, $$entry:WORD, $$retcode:WORD, @@instcount:WORD
- LOCAL save_dx, save_cx, save_bx, save_ax, save_di, save_si = LCLSIZE
- IFDEF VMDEBUG
- DATASEG
- NULLEN = 8 ; 8 first words of DATASEG...
- @@null DW NULLEN DUP (?) ; ... should be constants
- CODESEG
- push ds
- pop es
- xor si, si
- lea di, [@@null]
- mov cx, NULLEN
- rep movsw
- ENDIF
- mov [reset_bp], bp ; Set up initial interpreter parameters
- mov si, [$$entry]
- mov si, [si]
- mov bx, [cb_reg.page]
- cmp [ptype+bx], CODETYPE ; does page contain code ?
- jne @@notcode
- ldpage es, bx
- jmp next
- @@notcode:
- lea ax, [@@codeblock]
- DATASEG
- @@codeblock DB "[VM INTERNAL ERROR] %x:%04x isn't a code base", LF, 0
- CODESEG
- call zprintf C, ax, bx, [cb_reg.disp]
- mov ax, RV_CLOBBERED
- jmp in_debug
-
- IFDEF VMDEBUG
- @@nexttrace: ; **** FIRST PART OF TESTS: INTERNALS
- lea dx, [@@backward]
- DATASEG
- @@backward DB "[VM INTERNAL ERROR] interp: instruction preceding %x:%04x set direction flag", LF, 0
- CODESEG
- pushf ; Check direction flag is forward
- pop ax
- test ax, 400h ; test direction flag
- cld
- jnz @@clobbered
-
- lea dx, [@@stackptr]
- DATASEG
- @@stackptr DB "[VM INTERNAL ERROR] interp: instruction preceding %x:%04x corrupted 8086 stack", LF, 0
- CODESEG
- lea ax, [BP-LCLSIZE-USESSIZE] ; load the theoretic SP
- cmp ax, sp
- jne @@clobbered
-
- lea dx, [@@heapstr]
- DATASEG
- @@heapstr DB "[VM INTERNAL ERROR] interp: instruction preceding %x:%04x corrupted 8086 heap", LF, 0
- CODESEG
- push es
- call heapcheck C
- pop es
- or ax, ax
- js @@clobbered
-
- lea dx, [@@nullstr]
- DATASEG
- @@nullstr DB "[VM INTERNAL ERROR] interp: null ptr assignment at instruction preceding %x:%04x", LF, 0
- CODESEG
- push es
- push si
- push ds ; Compare from [DS:0] to [DS:@@null]
- pop es
- xor si, si
- lea di, [@@null]
- mov cx, NULLEN
- repe cmpsw
- pop si
- pop es
- je @@notclobbered
-
- @@clobbered: ; **** GENERIC CLOBBERED ANNOUNCE
- mov ax, [cb_reg.page]
- corpage ax
- call zprintf C, dx, ax, si
- mov bx, [$$retcode] ; return the intructions already done
- mov ax, [@@instcount]
- mov [bx], ax
- mov ax, RV_CLOBBERED
- jmp in_debug
-
- @@notclobbered: ; **** SECOND PART OF TESTS: VM
- lea dx, [@@reg0]
- DATASEG
- @@reg0 DB "[VM INTERNAL ERROR] interp: instruction preceding %x:%04x clobbered a register", LF, 0
- CODESEG
- cmp [reg0.page], NIL_PAGE*2 ; Check R0 is still nil
- jne @@clobbered
- cmp [reg0.disp], NIL_DISP
- jne @@clobbered
-
- push es
- mov ax, NILPAGE ; Verify that NILPAGE still contains
- mov es, ax ; (() . ())
- xor di, di
- mov cx, 3
- xor ax, ax
- repe scasw
- pop es
- jne @@clobbered
-
- ; Validate the contents of each of the Scheme registers
- mov cx, NUM_REGS ; load number of register into cx (counter)
- lea di, [regs]
- @@checkregs:
- mov ax, [(REG di).page]
- cmp ax, SPECFIX*2 ; does register contain a fixnum?
- je @@regok
- cmp ax, SPECCHAR*2 ; does register contain a character?
- je @@regok
- mov bx, ax ; save page number (times 2)
- ror ax, 1
- cmp ax, [nextpage] ; is page number too large?
- jae @@clobbered
- mov ax, [(REG di).disp]
- cmp ax, [psize+bx] ; is offset too big?
- jae @@clobbered
- @@regok:
- add di, size REG
- loop @@checkregs
- call @REG@check$qv C ; check for other registers
- DATASEG
- @@regchk DB "[VM INTERNAL ERROR] interp: instruction preceding %x:%04x clobbered class REG", LF, 0
- CODESEG
- lea dx, [@@regchk]
- or ax, ax
- jnz @@clobbered ; **** END OF TESTS
-
- sub [@@instcount], 1 ; 1 more instruction done
- jae @@nextgo
- mov ax, RV_PROCEED
- jmp in_exit
-
- @@nextgo:
- get1op ; Fetch next instruction's opcode
- mov ah, 0
- mov bx, ax
- shl bx, 1 ; Multiply opcode by two for use as index
- mov di, bx
- add [WORD icount+bx+di], 1 ; accounting info
- adc [WORD icount+bx+di+2], 0
- jmp [op_table+bx]
-
- LABEL $$sm$trace WORD
- jmp SHORT @@@trace+($-$$sm$entry) ; jump to overwrite "next" for debug
- @@@trace:
- jmp @@nexttrace
-
- LABEL $$sm$debug WORD
- jmp SHORT @@@debug+($-$$sm$entry) ; jump to force debug mode
- @@@debug:
- jmp in_debug
- ENDIF
-
- LABEL $$sm$timer WORD
- jmp SHORT @@@timer+($-$$sm$entry) ; jump to force timeout
- @@@timer:
- jmp timeout
-
- LABEL $$sm$mouse WORD
- jmp SHORT @@@mouse+($-$$sm$entry) ; jump to force timeout
- @@@mouse:
- jmp mouseevent
-
- LABEL $$sm$break WORD
- jmp SHORT @@@sdebug+($-$$sm$entry) ; jump to force Scheme debug mode
- @@@sdebug:
- jmp sc_debug
-
- LABEL $$sm$go WORD
- IFDEF HARDDEBUG
- jmp @@nexttrace
- ELSE
- xor ax, ax ; same as in next
- ENDIF
- ;
- ; Following is the main vm interpreter loop. Note that the location at $$sm$entry
- ; can (and will be) code modified to jump into the debugger, and a trace loop.
- ;
- next_pc:
- mov si, [save_si] ; Reload interpreter's PC
- mov bx, [cb_reg.page]
- ldpage es, bx
- cld
- next:
- LABEL $$sm$entry WORD
- IFDEF HARDDEBUG
- jmp @@nexttrace
- ELSE
- xor ax, ax ; Clear high order BYTE of ax
- ENDIF
- get1op
- mov bx, ax
- shl bx, 1
- jmp [op_table+bx]
-
- ;************************************************************************
- ;* Jump if nil, short JNILS reg,offset *
- ;************************************************************************
- PROC j_nil_s
- get2op
- mov bl, al ; copy register number
- cmp [regs+bx.bpage], 0 ; test for null pointer
- jne next
- mov al, ah
- cbw ; Sign extend short displacement
- add si, ax ; Add jump offset to current PC
- jmp next
- ENDP j_nil_s
-
- ;************************************************************************
- ;* Jump if not nil, short JNNILS reg,offset *
- ;************************************************************************
- PROC j_nnil_s
- get2op
- mov bl, al ; copy register number
- cmp [regs+bx.bpage], 0 ; test for null pointer
- je next
- mov al, ah
- cbw ; Sign extend short displacement
- add si, ax ; Add jump offset to current PC
- jmp next
- ENDP j_nnil_s
-
- ;************************************************************************
- ;* Jump if atom,short JATOMS reg,offset *
- ;************************************************************************
- PROC j_atm_s
- get2op
- mov bl, al ; copy register number to test
- test [attrib+bx], ATOM ; test for atom attribute
- jz next
- mov al, ah ; position branch offset and
- cbw ; sign extend to 16 bits
- add si, ax ; add jump offset to current PC
- jmp next
- ENDP j_atm_s
-
- ;************************************************************************
- ;* Jump if not atom,short JNATOMS reg,offset *
- ;************************************************************************
- PROC j_natm_s
- lods [WORD es:si] ; Load register, offset
- mov bl, al ; copy register number to test
- test [attrib+bx], ATOM ; test for atom attribute
- jnz next
- mov al, ah ; position branch offset and
- cbw
- add si, ax ; add jump offset to current PC
- jmp next
- ENDP j_natm_s
-
- ;************************************************************************
- ;* Jump if eq?, short JEQS src1,src2,offset *
- ;************************************************************************
- PROC j_eq_s
- get2op
- mov bl, ah
- mov di, bx
- mov bl, al ; copy src1 register number
- get1op
- cbw
- in_j_eq_s:
- mov cx, [regs+bx.disp]
- cmp cx, [regs+di.disp] ; are displacements eq?
- jne next
- mov cl, [regs+bx.bpage]
- cmp cl, [regs+di.bpage] ; are page numbers eq?
- jne next
- add si, ax ; add offset to current PC
- jmp next
- ENDP j_eq_s
-
- ;************************************************************************
- ;* Jump if not eq?, short JNEQS src1,src2,offset *
- ;************************************************************************
- PROC j_neq_s
- get2op
- mov bl, ah
- mov di, bx
- mov bl, al ; copy src1 register number
- get1op
- cbw
- in_j_neq_s:
- mov cx, [regs+bx.disp]
- cmp cx, [regs+di.disp] ; are displacements eq?
- jne @@jump
- mov cl, [regs+bx.bpage]
- cmp cl, [regs+di.bpage] ; are page numbers eq?
- jne @@jump
- jmp next
- @@jump:
- add si, ax ; add offset to current PC
- jmp next
- ENDP j_neq_s
-
- ;************************************************************************
- ;* Jump if eq?, long JEQL src1,src2,offset *
- ;************************************************************************
- PROC j_eq_l
- get2op
- mov bl, ah
- mov di, bx
- mov bl, al ; copy src1 register number
- lods [WORD es:si] ; load branch displacement
- jmp in_j_eq_s
- ENDP j_eq_l
-
- ;************************************************************************
- ;* Jump if not eq?, long JNEQL src1,src2,offset *
- ;************************************************************************
- PROC j_neq_l
- get2op
- mov bl, ah
- mov di, bx
- mov bl, al ; copy src1 register number
- lods [WORD es:si] ; load branch displacement, save
- jmp in_j_neq_s
- ENDP j_neq_l
-
- ;************************************************************************
- ;* Jump if nil, long JNILL reg,offset *
- ;************************************************************************
- PROC j_nil_l
- get1op
- mov bl, al
- cmp [regs+bx.bpage], 0 ; Test for null pointer
- jne @@dontjump
- lods [WORD es:si] ; load branch offset
- add si, ax ; Add jump offset to current PC
- jmp next
- @@dontjump:
- add si, 2
- jmp next ; Return to interpreter
- ENDP j_nil_l
-
- ;************************************************************************
- ;* Jump if not nil, long JNNILL reg,offset *
- ;************************************************************************
- PROC j_nnil_l
- get1op
- mov bl, al ; copy register number
- cmp [regs+bx.bpage], 0 ; Test for null pointer
- jz @@dontjump
- lods [WORD es:si] ; load branch offset
- add si, ax ; Add jump offset to current PC
- jmp next
- @@dontjump:
- add si, 2
- jmp next
- ENDP j_nnil_l
-
- ;************************************************************************
- ;* Jump if atom,long JATOMS reg,offset *
- ;************************************************************************
- PROC j_atm_l
- get1op
- mov bl, al ; copy register number to test
- test [attrib+bx], ATOM ; test for atom attribute
- jz @@dontjump
- lods [WORD es:si] ; load branch offset
- add si, ax ; add jump offset to current PC
- jmp next
- @@dontjump:
- add si, 2
- jmp next
- ENDP j_atm_l
-
- ;************************************************************************
- ;* Jump if not atom,long JNATOMS reg,offset *
- ;************************************************************************
- PROC j_natm_l
- get1op
- mov bl, al ; copy register number to test
- test [attrib+bx], ATOM ; test for atom attribute
- jnz @@dontjump
- lods [WORD es:si] ; load branch offset
- add si, ax ; add jump offset to current PC
- jmp next
- @@dontjump:
- add si, 2
- jmp next
- ENDP j_natm_l
-
- ;************************************************************************
- ;* Jump unconditionally, short *
- ;************************************************************************
- PROC jmp_shrt
- get1op
- cbw ; sign extend the BYTE offset
- add si, ax
- jmp next
- ENDP jmp_shrt
-
- ;************************************************************************
- ;* Jump unconditionally, long *
- ;************************************************************************
- PROC jmp_long
- lods [WORD es:si]
- add si, ax
- jmp next
- ENDP jmp_long
-
- ;************************************************************************
- ;* Move register to register: COPY dest,src *
- ;************************************************************************
- PROC copy
- get2op
- mov bl, ah ; copy source register number into
- mov cx, [regs+bx.disp]
- mov dl, [regs+bx.bpage]
- mov bl, al ; copy destination register number
- mov [regs+bx.disp], cx
- mov [regs+bx.bpage], dl
- jmp next
- ENDP copy
-
- ;************************************************************************
- ;* al ah *
- ;* Load constant from constant's area LD-CONST dest,const *
- ;* *
- ;* Purpose: Interpreter support for loading a compile time constant *
- ;* into a register of the Scheme virtual machine. *
- ;************************************************************************
- PROC ld_const
- get2op
- mov bl, ah ; load constant number
- mov di, bx
- shl di, 1
- add di, [cb_reg.disp]
- mov dl, [(CODEDEF es:bx+di).consts.page]
- mov cx, [(CODEDEF es:bx+di).consts.disp]
- mov bl, al ; load destination register number
- mov [regs+bx.bpage], dl
- mov [regs+bx.disp], cx
- jmp next
- ENDP ld_const
-
- ;************************************************************************
- ;* al ah *
- ;* Load immediate value LD-IMM dest,imm *
- ;* *
- ;* Purpose: Interpreter support for loading an immediate value *
- ;* into a register of the Scheme virtual machine. *
- ;************************************************************************
- PROC ld_imm
- get2op
- mov bl, al ; copy the destination register number
- mov al, ah ; isolate and sign extend the
- cbw ; immediate value
- mov [regs+bx.disp], ax
- mov [regs+bx.bpage], SPECFIX*2
- jmp next
- ENDP ld_imm
-
- ;************************************************************************
- ;* Load nil ld-nil dest *
- ;* *
- ;* Purpose: Scheme interpreter support to load the value "nil" into *
- ;* a VM register *
- ;************************************************************************
- PROC ld_nil
- get1op
- mov bl, al
- xor ax, ax
- mov [regs+bx.bpage], al ; store value of 'nil into
- mov [regs+bx.disp], ax ; destination register
- jmp next
- ENDP ld_nil
-
- ;************************************************************************
- ;* al ah *
- ;* Vector Load with short offset LD-VEC-S vect,offset *
- ;* *
- ;* Purpose: Scheme interpreter support for vector load instructions *
- ;* with short offset fields *
- ;************************************************************************
- PROC ld_off_s
- get2op
- mov bl, al ; copy vector pointer/destination reg
- mov di, bx
- mov al, ah
- cbw
- jmp in_ld_off_rs
- ENDP ld_off_s
-
- ;************************************************************************
- ;* al ax *
- ;* Vector Load with long offset LD-VEC-L vect,offset *
- ;* *
- ;* Purpose: Scheme interpreter support for vector load instructions *
- ;* with long offset fields *
- ;************************************************************************
- PROC ld_off_l
- mov dx, 4 ; record length of this instruction
- get1op
- mov di, ax
- lods [WORD es:si]
- jmp in_ld_off_r
- ENDP ld_off_l
-
- ;************************************************************************
- ;* al ah *
- ;* Vector Load with register offset LD-VEC-R vect,offset *
- ;* *
- ;* Purpose: Scheme interpreter support for vector load instructions *
- ;* with register offset fields *
- ;************************************************************************
- PROC ld_off_r
- get2op
- mov bl, al ; copy vector pointer/destination reg
- mov di, bx
- mov bl, ah ; copy number of index register
- cmp [regs+bx.bpage], SPECFIX*2 ; index a fixnum?
- je @@argsok
- @@badarg:
- lea bx, [@@msg]
- DATASEG
- @@msg DB "VECTOR-REF", 0
- CODESEG
- jmp src_err
- @@argsok:
- mov ax, [regs+bx.disp]
- in_ld_off_rs:
- mov dx, 3 ; record length of this instruction
- in_ld_off_r:
- save <si>
- mov cx, ax ; multiply the index value by 3
- shl ax, 1
- add ax, cx
- jl @@bounds
- mov bl, [regs+di.bpage]
- cmp [ptype+bx], VECTTYPE ; does it point to a vector?
- jne @@badarg
- ldpage es, bx
- mov si, [regs+di.disp]
- add ax, OFFSET (TYPE VECDEF).data
- cmp ax, [(VECDEF es:si).len] ; is reference within bounds?
- jge @@bounds
- add si, ax ; add index to vector offset
- mov al, [(POINTER es:si).page]
- mov bx, [(POINTER es:si).disp]
- mov [regs+di.bpage], al
- mov [regs+di.disp], bx
- jmp next_pc
- @@bounds:
- lea ax, [@@msg]
- in_off_error:
- restore <si>
- sub si, dx ; back up to start of instruction
- push es ; saves es over C call
- call disassemble C, ax, si ; disassemble instruction for *irritant*
- mov ax, 1
- mov bx, VECTOR_OFFSET_ERROR
- call set_numeric_error C, ax, bx, [tmp_adr]
- pop es
- restore <si>
- jmp sch_err
- ENDP ld_off_r
-
- ;************************************************************************
- ;* al ah al *
- ;* Vector Store with short offset ST-VEC-S vect,offset,src *
- ;* *
- ;* Purpose: Scheme interpreter support for vector store instructions*
- ;* with short offset fields *
- ;************************************************************************
- PROC st_off_s
- get2op
- mov bl, al ; copy vector pointer register
- mov di, bx
- mov al, ah
- cbw
- jmp in_st_off_rs
- ENDP st_off_s
-
- ;************************************************************************
- ;* al ax al *
- ;* Vector Store with long offset ST-VEC-L vect,offset,src *
- ;* *
- ;* Purpose: Scheme interpreter support for vector store instructions*
- ;* with long offset fields *
- ;************************************************************************
- PROC st_off_l
- mov dx, 5 ; record length of this instruction
- get1op
- mov di, ax
- lods [WORD es:si]
- jmp in_st_off_r
- ENDP st_off_l
-
- ;************************************************************************
- ;* al ah al *
- ;* Vector Store with register offset ST-VEC-R vect,offset,src *
- ;* *
- ;* Purpose: Scheme interpreter support for vector store instructions*
- ;* with register offset fields *
- ;************************************************************************
- PROC st_off_r
- get2op
- mov bl, al ; copy vector pointer register
- mov di, bx
- mov bl, ah ; copy number of index register
- cmp [regs+bx.bpage], SPECFIX*2 ; index a fixnum?
- jne @@badarg
- mov ax, [regs+bx.disp]
- in_st_off_rs:
- mov dx, 4
- in_st_off_r:
- mov cx, ax
- shl ax, 1
- add cx, ax ; multiply the index value by 3
- get1op
- save <si>
- jl @@bounds ; flags still set by 'add' !
- xor ah, ah ; ax is source reg
- mov bl, [regs+di.bpage] ; load page number for vector ptr
- cmp [ptype+bx], VECTTYPE ; does it point to a vector?
- jne @@badarg
- ldpage es, bx ; load paragraph address for vector's page
- mov si, [regs+di.disp]
- add cx, OFFSET (TYPE VECDEF).data
- cmp cx, [(VECDEF es:si).len] ; is reference within bounds?
- jge @@bounds
- add si, cx ; add index to vector offset
- mov di, ax ; copy src reg # into di
- mov al, [regs+di.bpage]
- mov bx, [regs+di.disp]
- mov [(POINTER es:si).page], al
- mov [(POINTER es:si).disp], bx
- jmp next_pc
- @@bounds:
- lea ax, [@@msg]
- DATASEG
- @@msg DB "VECTOR-SET!", 0
- CODESEG
- jmp in_off_error
- @@badarg:
- lea bx, [@@msg]
- jmp src_err
- ENDP st_off_r
-
- ;************************************************************************
- ;* Negation (minus obj) MINUS dest *
- ;************************************************************************
- PROC minus
- get1op
- mov di, ax
- cmp [regs+di.page], SPECFIX*2
- jne @@notfix
- mov ax, [regs+di.disp]
- in_minus:
- neg ax ; negate the immediate value
- jo @@overflow
- mov [regs+di.disp], ax
- jmp next
- @@notfix:
- mov dx, MINUS_OP ; indicate negation sub-opcode
- in_arith: ; Process unary operation out of line
- save <si>
- add di, OFFSET regs
- call arith1 C, dx, di ; call unary arithmetic support
- or ax, ax ; was error encountered?
- jnz @@aritherror
- jmp next_pc
- @@aritherror:
- jmp sch_err
-
- @@overflow:
- mov ax, 8000h ; it could only be (- #\h8000)
- xor dx, dx
- in_enlargelong:
- save <si>
- add di, OFFSET regs
- call enlarge C, di, ax, dx ; create bignum
- jmp next_pc
- ENDP minus
-
- ;************************************************************************
- ;* Support for absolute value (abs n) *
- ;************************************************************************
- PROC sabs
- get1op
- mov di, ax
- cmp [regs+di.page], SPECFIX*2
- jne @@notfix
- mov ax, [regs+di.disp]
- or ax, ax ; how's it relate to zero?
- js in_minus
- jmp next
- @@notfix:
- mov dx, ABS_OP
- jmp in_arith
- ENDP sabs
-
- ;************************************************************************
- ;* Macro support for out-of-line calls to Borland C *
- ;************************************************************************
- MACRO TESTARG
- or ax, ax ; was error detected?
- jl @@error
- jmp next_pc
- @@error:
- jmp sch_err
- ENDM
-
- ;************************************************************************
- ; Convert number to fixnum (toward NEARest integer) ROUND reg *
- ;************************************************************************
- PROC sround
- call get1parm
- call around C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ; Convert number to fixnum (toward - infinity) FLOOR reg *
- ;************************************************************************
- PROC sfloor
- call get1parm
- call afloor C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ; Convert number to fixnum (toward + infinity) CEILING reg *
- ;************************************************************************
- PROC sceiling
- call get1parm
- call aceiling C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ; Convert number to fixnum (toward zero) TRUNCATE reg *
- ;************************************************************************
- PROC struncat
- call get1parm
- call atruncate C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ; Convert number to fixnum FLOAT reg *
- ;************************************************************************
- PROC float
- call get1parm
- call sfloat C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for string->symbol (string->symbol dest) *
- ;************************************************************************
- PROC str2sym
- call get1parm
- call str_2_sym C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* string->uninterned-symbol (string->uninterned-symbol dest)*
- ;************************************************************************
- PROC str2usym
- call get1parm
- call str_2_usym C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for symbol->string (symbol->string dest) *
- ;************************************************************************
- PROC sym2str
- call get1parm
- call sym_2_str C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for read-line *
- ;************************************************************************
- PROC srd_line
- get1op
- save <si>
- add ax, OFFSET regs
- push ax
- xor bx, bx
- call get_port C, ax, bx ; get the port object
- test ax, ax ; error returned?
- pop cx ; restore main reg
- jnz @@error
- call sread_ln C, cx, [tmp_reg.page], [tmp_reg.disp]
- jmp next_pc
- @@error:
- lea bx, [@@msg]
- jmp src_err
- DATASEG
- @@msg DB "READ-LINE", 0
- CODESEG
- ENDP srd_line
-
- ;************************************************************************
- ;* Support for read-atom *
- ;************************************************************************
- PROC srd_atom
- get1op
- save <si>
- add ax, OFFSET regs
- push ax
- xor bx, bx
- call get_port C, ax, bx ; get the port object
- test ax, ax ; error returned?
- pop cx
- jnz @@error
- call sread_atom C, cx, [tmp_reg.page], [tmp_reg.disp]
- jmp next_pc
- @@error:
- lea bx, [@@msg]
- jmp src_err
- DATASEG
- @@msg DB "READ-ATOM", 0
- CODESEG
- ENDP srd_atom
-
- ;************************************************************************
- ;* Support for push_char *
- ;************************************************************************
- PROC unread_char
- get1op
- save <si>
- add ax, OFFSET regs
- xor cx, cx
- call get_port C, ax, cx
- test ax,ax ; check return status
- jnz @@error
-
- call ssetadr C, [tmp_reg.page], [tmp_reg.disp]
- call pushchar C
- jmp next_pc
-
- @@error: ; Wrong port object, display error
- lea bx, [@@msg]
- jmp src_err
-
- DATASEG
- @@msg DB "UNREAD-CHAR", 0
- CODESEG
- ENDP unread_char
-
- ;************************************************************************
- ;* Support for read-char-ready? *
- ;************************************************************************
- PROC rd_char_rdy
- get1op
- save <si>
- add ax, OFFSET regs ; compute register address
- mov di, ax
- xor cx, cx
- call get_port C, ax, cx
- test ax,ax ; check return status
- jz @@portok
- jmp @@error
-
- @@portok:
- mov [(REG di).page], SPECCHAR*2 ; prepare to return a char
- mov si, [tmp_reg.disp]
- mov bx, [tmp_reg.page]
- ldpage es, bx
- mov bx, [(PORTDEF es:si).bufpos] ; input buffer starting position
- cmp bx, [(PORTDEF es:si).bufend] ; compare with ending position
- jge @@endbuffer
- xor ah, ah
- mov al, [(PORTDEF es:si+bx).buffer] ; get the character
- @@testchar:
- cmp al, CTRL_Z ; End-Of-File ?
- jne @@return
- mov bx, [(PORTDEF es:si).pflags]
- and bx, PORT_BINARY ; binary file?
- jnz @@return
- @@eof:
- mov [(REG di).page], EOF_PAGE*2 ; return eof character
- mov [(REG di).disp], EOF_DISP
- jmp next_pc
-
- @@return:
- mov [(REG di).disp], ax ; return the character
- jmp next_pc
-
- @@endbuffer:
- mov ax, [(PORTDEF es:si).pflags]
- test ax, PORT_TYPE ; window?
- jnz @@nowindow
- call GETCHready C ; any character?
- test ax, ax
- jz @@nochar
- mov ah, 0 ; yes
- jmp @@return
-
- @@nochar: ; no character available. return '()
- mov [(REG di).page], NIL_PAGE
- mov [(REG di).disp], NIL_DISP
- jmp next_pc
-
- @@nowindow:
- test ax, READ_OPEN ; open?
- jz @@nochar
- call ssetadr C, [tmp_reg.page], [tmp_reg.disp]
- call take_ch C ; get one character
- cmp ax, 256 ; eof?
- je @@eof
- push ax
- call pushchar C ; no, put it back
- pop ax
- jmp @@return
-
- @@error: ; Wrong port object, display error
- lea bx, [@@msg]
- jmp src_err
-
- DATASEG
- @@msg DB "CHAR-READY?", 0
- CODESEG
- ENDP rd_char_rdy
-
- ;************************************************************************
- ;* Support for read-char *
- ;************************************************************************
- PROC read_char
- get1op
- save <si>
- add ax, OFFSET regs ; compute register address
- mov di,ax
- xor cx,cx
- call get_port C, ax, cx
- test ax,ax ; check return status
- jz @@portok
- jmp @@error
-
- @@portok:
- mov [(REG di).page], SPECCHAR*2
- mov bx, [tmp_reg.page]
- ldpage es, bx
- mov si, [tmp_reg.disp]
- mov ax, [(PORTDEF es:si).pflags] ; get port flags
- test ax, PORT_TYPE ; window object?
- jnz @@readchar
- mov bx, [(PORTDEF es:si).bufpos] ; input buffer starting position
- cmp bx, [(PORTDEF es:si).bufend] ; compare with ending position
- jl @@readchar
- mov cx, [(PORTDEF es:si).curline]
- add cx, [(PORTDEF es:si).ulline]
- mov dx, [(PORTDEF es:si).curcol]
- add dx, [(PORTDEF es:si).ulcol]
- push ax
- mov ax, [(PORTDEF es:si).text]
- mov [t_attrib], ax
- pop ax
-
- call zputcur C, cx, dx ; cursor position
- call zcuron C ; cursor on
- call GETCH C ; get character
- mov ah, 0
- mov [(REG di).disp], ax
- mov bx, [tmp_reg.page]
- ldpage es, bx
- mov [(PORTDEF es:si).buffer], al ; store in port object
- call zcuroff C ; cursor off
- mov bx,1
- mov [(PORTDEF es:si).bufpos], bx
- mov [(PORTDEF es:si).bufend], bx
- jmp next_pc
-
- @@readchar:
- call ssetadr C, [tmp_reg.page],[tmp_reg.disp] ; set port address
- call take_ch C ; take one character
- cmp ax, 256 ; eof?
- je @@eof
- mov [(REG di).disp], ax ; return the character
- jmp next_pc
- @@eof:
- mov [(REG di).page], EOF_PAGE*2 ; return eof character
- mov [(REG di).disp], EOF_DISP
- jmp next_pc
-
- @@error:
- lea bx, [@@msg] ; address of error message
- jmp src_err
-
- DATASEG
- @@msg DB "READ-CHAR", 0
- CODESEG
- ENDP read_char
-
- ;************************************************************************
- ;* Support for fast load (fasl filename) *
- ;************************************************************************
- PROC sfasl
- call get1parm
- call fasl C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for %push-history (%push-history string) *
- ;************************************************************************
- PROC push_hist
- call get1parm
- call pushhistory C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for %get-history (%get-history string) *
- ;************************************************************************
- PROC get_hist
- call get1parm
- call gethistory C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for clear-history (clear-history) *
- ;************************************************************************
- PROC clr_hist
- lea ax, [history]
- mov [histpos], ax
- mov [histend], ax
- jmp next
- ENDP
-
- ;************************************************************************
- ;* Support for prop-list (prop-list name)*
- ;************************************************************************
- PROC proplist
- call get1parm
- call prop_list C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for random (random seed) *
- ;************************************************************************
- PROC random
- call get1parm
- call srandom C, ax
- jmp next_pc
- ENDP
-
- ;************************************************************************
- ;* Support for clear-window (clear-window dest) *
- ;************************************************************************
- PROC clr_wind
- call get1parm
- call clear_window C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for close-port (close-port port) *
- ;************************************************************************
- PROC p_close
- call get1parm
- call spclose C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for %start-timer (%start-timer #-ticks) *
- ;************************************************************************
- PROC set_tim
- call get1parm
- call cset_tim C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for %stop-timer (%stop-timer) *
- ;************************************************************************
- PROC rst_tim
- call get1parm
- call crst_tim C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for STRING-LENGTH (STRING-LENGTH STRING) *
- ;************************************************************************
- PROC str_lng
- call get1parm
- call st_len C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for Object-Hash, -Unhash *
- ;************************************************************************
- PROC obj_hash
- get1op
- save <si>
- add ax, OFFSET regs
- call objhash C, ax
- jmp next_pc
- ENDP obj_hash
-
- PROC obj_unhs
- get1op
- save <si>
- add ax, OFFSET regs
- call objunhash C, ax
- jmp next_pc
- ENDP obj_unhs
-
- ;************************************************************************
- ;* Support for REIFY-STACK (REIFY-STACK index) *
- ;************************************************************************
- PROC reify_s
- xor cx, cx ; Read subfunction
- call get1parm
- in_reify_s:
- call reif_stk C, ax, bx, cx
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for get-prop (get-prop name prop) *
- ;************************************************************************
- PROC getprop
- call get2parm
- call get_prop C, ax, bx
- jmp next_pc
- ENDP
-
- ;************************************************************************
- ;* Support for rem-prop (rem-prop name prop) *
- ;************************************************************************
- PROC remprop
- call get2parm
- call rem_prop C, ax, bx
- jmp next_pc
- ENDP
-
- ;************************************************************************
- ;* Support for open-port (open port mode) *
- ;************************************************************************
- PROC p_open
- call get2parm
- call spopen C, ax, bx
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for REIFY-STACK! (REIFY-STACK! index value) *
- ;************************************************************************
- PROC reify_sb
- call get2parm ; Get parameters
- mov cx, 1 ; Write subfunction
- jmp in_reify_s
- ENDP
-
- ;************************************************************************
- ;* Support for APPEND (APPEND list obj) *
- ;************************************************************************
- PROC append
- call get2parm
- call sappend C, ax, bx
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for put-prop (put-prop name value prop) *
- ;************************************************************************
- PROC putprop
- call get3parm
- call put_prop C, cx, ax, bx
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Substring (substring string position length) SUBSTR str,pos,len *
- ;************************************************************************
- PROC substring
- call get3parm
- call ssubstr C, cx, ax, bx
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for set-window-attr (get-window-attribute wind attr val) *
- ;************************************************************************
- PROC set_w_at
- call get3parm
- call set_window_attribute C, cx, ax, bx
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Interface to set file position (set-file-position! port chunk# BYTEs)*
- ;************************************************************************
- PROC sfpos
- call get3parm
- call set_pos C, cx, ax, bx
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for make-port (make-port typesymbol source) *
- ;************************************************************************
- PROC port_make
- call get2parm
- call make_port C, ax, bx
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for %port-get-attribute (%port-get-attribute port attr) *
- ;************************************************************************
- PROC port_get
- call get2parm
- call port_get_attribute C, ax, bx
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for %port-set-attribute! (%port-set-attribute! port attr val)*
- ;************************************************************************
- PROC port_set
- call get3parm
- call port_set_attribute C, cx, ax, bx
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for %read-char (%read-char port) *
- ;************************************************************************
- PROC port_char
- call get1parm
- call port_read_char C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for %read-line (%read-line port) *
- ;************************************************************************
- PROC port_line
- call get1parm
- call port_read_line C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for %char-ready? (%char-ready? port) *
- ;************************************************************************
- PROC port_ready
- call get1parm
- call port_char_ready C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for %peek-char (%peek-char port) *
- ;************************************************************************
- PROC port_peek
- call get1parm
- call port_peek_char C, ax
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for %str-str (%str-str str start end match direction case) *
- ;************************************************************************
- PROC str_str
- call get4parm
- push ax bx
- call get2parm
- mov di, ax ; DIrection
- mov si, bx ; senSItivity
- mov di, [(REG di).page] ; #f means forward
- mov si, [(REG si).page] ; #f means insensitive
- pop bx ax
- call str_srch_str C, cx, dx, ax, bx, di, si
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* Support for subst.-find-prev-char-in-set (... str start end charset) *
- ;************************************************************************
- PROC srch_pr
- mov di, -1 ; set direction backward
- jmp search_char
- ENDP
-
- ;************************************************************************
- ;* Support for subst.-find-next-char-in-set (... str start end charset) *
- ;************************************************************************
- PROC srch_nx
- xor di, di ; set direction forward
- search_char:
- call get4parm
- call srch_str C, cx, dx, ax, bx, di
- TESTARG
- ENDP
-
- ;************************************************************************
- ;* al ah al *
- ;* Support for "reification" (%reify obj index) *
- ;* (%reify! obj index val) *
- ;************************************************************************
- PROC sreifyb
- mov cx, 1 ; set flag for "store" operation
- jmp in_sreify
- ENDP sreifyb
- PROC sreify
- xor cx, cx ; set flag for "load" operation
- in_sreify:
- get2op
- xor bx, bx
- mov bl, al
- lea di, [regs+bx]
- mov bl, ah ; copy index's register number and
- add bx, OFFSET regs ; compute index register's address
- or cx, cx ; is this a load or a store?
- jz @@load
- xor ax, ax
- get1op
- add ax, OFFSET regs
- @@load:
- save <si>
- call reify C, cx, di, bx, ax
- or ax, ax ; test result of reification request
- jnz @@error
- jmp next_pc
- @@error:
- jmp sch_err
- ENDP sreify
-
- ;************************************************************************
- ;* Macro definition - Interpreter support for binary operations *
- ;* *
- ;* Purpose: To generate interpreter support for operations of the *
- ;* form: *
- ;* OP dest,src *
- ;* where: *
- ;* destination reg <- destination reg OP source reg*
- ;************************************************************************
- MACRO bin_op
- get2op
- mov bl, al
- mov di, bx
- mov al, [regs+di.bpage] ; test to see if destination's FIX
- cmp al, SPECFIX*2
- jne @@ool
- mov bl, ah ; copy source register number
- cmp al, [regs+bx.bpage] ; is second operand also a fixnum?
- jne @@ool
- mov bx, [regs+bx.disp] ; load source (second) operand
- mov ax, [regs+di.disp] ; load destination (first) operand
- ENDM
-
- MACRO bin_ret
- mov [regs+di.disp], ax ; store result into destination register
- @@tonext:
- jmp next
- ENDM
-
- ;************************************************************************
- ; Addition (+ obj1 obj2) ADDOP dest,src *
- ;************************************************************************
- PROC addproc
- bin_op
- add ax, bx
- jo add_overflow
- bin_ret
- sub_overflow:
- cmc ; complement the carry bit for subtract
- add_overflow:
- mov dx, 0 ; make a long
- sbb dx, 0
- jmp in_enlargelong ; convert to bignum
- @@ool:
- mov dx, ADD_OP ; load operation type
-
- ; General arithmetic support for non-integer binary arithmetic operations
- ; Registers at this point: ah - source register number
- ; bh - (zero)
- ; dx - arithmetic sub-opcode (operation type)
- ; di - destination register number
-
- bin_ool:
- save <si>
- mov bl, ah ; copy source register number
- add bx, OFFSET regs
- add di, OFFSET regs
- call arith2 C, dx, di, bx
- or ax, ax ; error encountered?
- jnz @@error
- jmp next_pc
- @@error:
- jmp sch_err
- ENDP addproc
-
- ;************************************************************************
- ;* Subtraction (- obj1 obj2) SUB dest,src*
- ;************************************************************************
- PROC subproc
- bin_op
- sub ax, bx
- jo @@overflow
- bin_ret
- @@ool:
- mov dx, SUB_OP
- jmp bin_ool
-
- @@overflow:
- mov dx, 0 ; make a long
- adc dx, 0ffffh
- jmp in_enlargelong ; convert to bignum
- ENDP subproc
-
- ;************************************************************************
- ;* Multiplication (* obj1 obj2) MUL dest,src *
- ;************************************************************************
- PROC mulproc
- bin_op
- imul bx
- jo mul_overflow
- bin_ret
- @@ool:
- mov dx, MUL_OP
- jmp bin_ool
- mul_overflow:
- jmp in_enlargelong
- ENDP mulproc
-
- ;************************************************************************
- ;* Division (/ obj1 obj2) DIV dest,src*
- ;************************************************************************
- PROC divproc
- bin_op
- or bx, bx ; is the divisor zero?
- jz @@zero
- cwd ; convert dividend to a doubleword
- idiv bx ; divide the two operands
- or dx, dx ; is remainder zero?
- jne @@fraction
- bin_ret
- @@ool:
- mov dx, DIV_OP
- jmp bin_ool
- divzero:
- @@zero:
- lea bx, [@@msg]
- DATASEG
- @@msg DB "/", 0
- CODESEG
- in_divproc:
- sub si, 3 ; back up location pointer to start of inst.
- call disassemble C, bx, si ; "disassemble" the instruction
- mov ax, 1
- mov bx, ZERO_DIVIDE_ERROR
- call set_numeric_error C, ax, bx, [tmp_adr]
- jmp sch_err
- @@fraction:
- add di, OFFSET regs
- push es ; saves es over C call
- call sfloat C, di ; convert destination op to flonum
- pop es
- sub si, 2 ; back up the location pointer
- xor bx, bx
- jmp divproc ; re-execute div in floating point
- ENDP divproc
-
- ;************************************************************************
- ;* Integer Division (quotient obj1 obj2) QUOTIENT dest,src *
- ;************************************************************************
- PROC quotient
- bin_op
- or bx, bx
- jz @@zero
- cwd ; convert dividend to a doubleword
- idiv bx
- bin_ret
- @@ool:
- mov dx, QUOT_OP
- jmp bin_ool
- @@zero:
- lea bx, [@@msg]
- DATASEG
- @@msg DB "QUOTIENT", 0
- CODESEG
- jmp in_divproc
- ENDP quotient
-
- ;************************************************************************
- ;* Remainder (remainder obj1 obj2) REMAINDER dest,src *
- ;************************************************************************
- PROC remainder
- bin_op
- or bx, bx
- jz @@zero
- cwd ; convert dividend to a doubleword
- idiv bx
- mov ax, dx
- bin_ret
- @@zero:
- lea bx, [@@msg]
- DATASEG
- @@msg DB "REMAINDER", 0
- CODESEG
- jmp in_divproc
- @@ool:
- mov dx, REM_OP
- jmp bin_ool
- ENDP remainder
-
- ;************************************************************************
- ;* Integer Division (divide obj1 obj2) DIVIDE dest,src *
- ;************************************************************************
- PROC divide
- bin_op
- or bx, bx
- jz @@zero
- cwd ; convert dividend to a doubleword
- mov cx, dx ; save sign of dividend
- idiv bx
- or dx, dx ; if no remainder, ok.
- jz @@ok
- xor bx, cx ; compare signs of dividend & divisor
- and bx, 8000h
- jz @@ok
- dec ax
- @@ok:
- bin_ret
-
- @@ool:
- mov dx, DIVIDE_OP
- jmp bin_ool
-
- @@zero:
- lea bx, [@@msg]
- DATASEG
- @@msg DB "DIVIDE", 0
- CODESEG
- jmp in_divproc
- ENDP divide
-
- ;************************************************************************
- ;* Modulo (modulo obj1 obj2) MODULO dest,src *
- ;************************************************************************
- PROC modulo
- bin_op
- or bx, bx
- jz @@zero
- cwd ; convert dividend to a doubleword
- idiv bx
- mov ax, dx
- xor dx, bx ; compare signs of rem. and divisor
- and dx, 8000h
- jz @@ok
- or ax, ax ; don't fix up 0
- jz @@ok
- add ax, bx
- @@ok:
- bin_ret
-
- @@zero:
- lea bx, [@@msg]
- DATASEG
- @@msg DB "MODULO", 0
- CODESEG
- jmp in_divproc
- @@ool:
- mov dx, MOD_OP
- jmp bin_ool
- ENDP modulo
-
- ;************************************************************************
- ;* Maximum value (max obj1 obj2) MAX dest,src*
- ;************************************************************************
- PROC maximum
- bin_op
- cmp ax, bx
- jge @@tonext
- mov ax, bx ; copy the source operand to ax
- bin_ret
- @@ool:
- mov dx, GE_OP ; load operation type
- max_ool:
- save <si>
- mov bl, ah ; copy source register number
- add bx, OFFSET regs
- add di, OFFSET regs
- push bx di
- call arith2 C, dx, di, bx
- pop di bx
- or ax, ax ; what was the result of the comparison?
- jl @@error
- jnz @@done
- mov ax, [(REG bx).disp] ; copy source operand into the destination
- mov bl, [(REG bx).bpage]
- mov [(REG di).disp], ax
- mov [(REG di).bpage], bl
- max_done:
- @@done:
- jmp next_pc
- @@error:
- jmp sch_err
- ENDP maximum
-
- ;************************************************************************
- ;* Minimum value (min obj1 obj2) MIN dest,src*
- ;************************************************************************
- PROC minimum
- bin_op
- cmp ax, bx
- jle @@tonext
- mov ax, bx ; copy the source operand to ax
- bin_ret
- @@ool:
- mov dx, LE_OP
- jmp max_ool
- ENDP minimum
-
- ;************************************************************************
- ;* (bitwise-xor obj1 obj2) XOR dest,src*
- ;************************************************************************
- PROC b_xor
- bin_op
- xor ax, bx
- bin_ret
- @@ool:
- mov dx, XOR_OP
- jmp bin_ool
- ENDP b_xor
-
- ;************************************************************************
- ;* (bitwise-and obj1 obj2) AND dest,src*
- ;************************************************************************
- PROC b_and
- bin_op
- and ax, bx
- bin_ret
- @@ool:
- mov dx, AND_OP
- jmp bin_ool
- ENDP b_and
-
- ;************************************************************************
- ;* (bitwise-or obj1 obj2) OR dest,src*
- ;************************************************************************
- PROC b_or
- bin_op
- or ax, bx
- bin_ret
- @@ool:
- mov dx, OR_OP
- jmp bin_ool
- ENDP b_or
-
- ;************************************************************************
- ;* Macro definition - Interpreter support for immediate operations *
- ;* *
- ;* Purpose: To generate interpreter support for operations of the *
- ;* form: *
- ;* OP dest,immediate *
- ;* where: *
- ;* destination reg <- destination reg OP immediate *
- ;************************************************************************
- MACRO immed_op
- get2op
- mov bl, al
- mov di, bx
- mov al, ah ; sign extend immediate operand
- cbw
- cmp [regs+di.bpage], SPECFIX*2 ; dest operand a fixnum?
- jne @@ool
- mov bx, ax ; move immediate operand to bx
- mov ax, [regs+di.disp] ; load destination (first) operand
- ENDM
-
- ;************************************************************************
- ;* Add immediate ADDI reg,val *
- ;************************************************************************
- PROC addi
- immed_op
- add ax, bx
- jo addi_overflow
- bin_ret
- addi_overflow:
- jmp add_overflow
- @@ool:
- mov dx, ADD_OP ; load operation type
-
- ; General arithmetic support for non-integer immediate operations
- ; Registers at this point: ax - immediate value
- ; dx - arithmetic sub-opcode (operation type)
- ; di - destination register number
-
- bini_ool:
- save <si>
- add di, OFFSET regs
- mov [tmp_reg.disp], ax
- mov [tmp_reg.page], SPECFIX*2
- call arith2 C, dx, di, [tmp_adr]
- or ax, ax
- jne @@error
- jmp next_pc
- @@error:
- jmp sch_err
- ENDP addi
-
- ;************************************************************************
- ;* Multiply Immediate MULI reg,val *
- ;************************************************************************
- PROC muli
- immed_op
- imul bx
- jo muli_overflow
- bin_ret
- muli_overflow:
- jmp mul_overflow
- @@ool:
- mov dx, MUL_OP
- jmp bini_ool
- ENDP muli
-
- ;************************************************************************
- ;* Divide Immediate DIVI reg,val *
- ;************************************************************************
- PROC divi
- immed_op
- or bx, bx ; is the divisor zero?
- jz @@zero
- cwd ; convert dividend to a doubleword
- idiv bx
- or dx, dx ; is remainder zero?
- jnz @@fraction
- bin_ret
- @@zero:
- jmp divzero
- @@fraction:
- add di, OFFSET regs
- push es ; saves es over C call
- call sfloat C, di ; convert destination op to flonum
- pop es
- sub si, 2 ; back up the location pointer
- xor bx, bx
- jmp divi ; re-execute div immed in floating point
- @@ool:
- mov dx, DIV_OP
- jmp bini_ool
- ENDP divi
-
- ;************************************************************************
- ;* Test for (null? obj) NULL? reg *
- ;************************************************************************
- PROC null_p
- get1op
- mov bx, ax
- cmp [regs+bx.bpage], 0
- je @@null
- xor ax, ax ; set register to nil (test false)
- mov [regs+bx.bpage], al
- mov [regs+bx.disp], ax
- jmp next
- @@null:
- mov [regs+bx.bpage], T_PAGE*2
- mov [regs+bx.disp], T_DISP
- jmp next
- ENDP null_p
-
- ;************************************************************************
- ;* al ah *
- ;* Test for eq? (pointers identical) EQ? dest,src *
- ;************************************************************************
- PROC eq_p
- get2op
- mov bl, al ; copy destination register number
- mov di, bx
- mov bl, ah ; copy source register number
- mov ax, [regs+bx.disp] ; load page number of source operand
- cmp ax, [regs+di.disp] ; are the displacements identical?
- jne @@noteq
- mov al, [regs+bx.bpage] ; load src operand's page number
- cmp al, [regs+di.bpage] ; are page numbers identical?
- jne @@noteq
- mov [regs+di.bpage], T_PAGE*2
- mov [regs+di.disp], T_DISP
- jmp next
- @@noteq:
- xor ax, ax
- mov [regs+di.bpage], al
- mov [regs+di.disp], ax
- jmp next
- ENDP eq_p
-
- ;************************************************************************
- ;* al ah *
- ;* Test for eqv? (pointers identical, or numbers equal) EQ? dest,src*
- ;************************************************************************
- PROC eqv_p
- get2op
- mov bl, al ; copy destination register in di
- mov di, bx
- mov bl, ah ; copy source register number
- mov ax, [regs+bx.disp]
- cmp ax, [regs+di.disp] ; are the displacements identical?
- jne @@ptrnoteq
- mov al, [regs+bx.bpage]
- cmp al, [regs+di.bpage] ; are page numbers identical?
- jne @@ptrnoteq
- mov [regs+di.bpage], T_PAGE*2
- mov [regs+di.disp], T_DISP
- jmp next
- @@ptrnoteq:
- mov ah, bl ; copy source register number and load
- mov bl, [regs+bx.bpage] ; page number from source reg
- test [attrib+bx], FIXNUMS or BIGNUMS or FLONUMS
- jz @@string
- mov ax, di ; copy destination register number and load
- mov bl, [regs+di.bpage] ; page number from dest reg
- test [attrib+bx], FIXNUMS or BIGNUMS or FLONUMS
- jz @@string
- sub si, 2 ; else set ip back to operands
- jmp eq_n ; and go test with "="
- @@string:
- test [attrib+bx], STRINGS
- jz @@fail
- add di, OFFSET regs
- jmp in_equal_p ; test using "equal?"
- @@fail:
- xor ax, ax
- mov [regs+di.bpage], al
- mov [regs+di.disp], ax
- jmp next
- ENDP eqv_p
-
- ;************************************************************************
- ;* al ah *
- ;* Test equality of s-expressions equal? dest,src*
- ;* *
- ;* Purpose: Scheme interpreter support for the testing of "equality"*
- ;* of two s-expressions. *
- ;************************************************************************
- PROC equal_p
- get2op
- mov bl, al ; copy destination register number
- lea di, [regs+bx] ; and load its address
- in_equal_p:
- save <si>
- mov bl, ah ; copy source register number
- add bx, OFFSET regs
- call sequal_p C, di, bx ; call: sequal(&dest,&src)
- or ax, ax ; are operands equal? (return code not zero)
- je @@fail
- mov [(REG di).bpage], T_PAGE*2
- mov [(REG di).disp], T_DISP
- jmp next_pc
- @@fail:
- mov [(REG di).bpage], al
- mov [(REG di).disp], ax
- jmp next_pc
- ENDP equal_p
-
- ;************************************************************************
- ;* Test for (atom? obj) *
- ;************************************************************************
- PROC atom_p
- mov dx, ATOM
- jmp in_list
- ENDP atom_p
-
- ;************************************************************************
- ;* Test for (char? obj) *
- ;************************************************************************
- PROC char_p
- mov dx, CHARS
- jmp in_list
- ENDP char_p
-
- ;************************************************************************
- ;* Test for (closure? obj) *
- ;************************************************************************
- PROC closur_p
- mov dx, CLOSURE
- jmp in_list
- ENDP closur_p
-
- ;************************************************************************
- ;* Test for (code? obj) *
- ;************************************************************************
- PROC code_p
- mov dx, CODE
- jmp in_list
- ENDP code_p
-
- ;************************************************************************
- ;* Test for (continuation? obj) *
- ;************************************************************************
- PROC contin_p
- mov dx, CONTINU
- jmp in_list
- ENDP contin_p
-
- ;************************************************************************
- ;* Test for (float? obj) *
- ;************************************************************************
- PROC float_p
- mov dx, FLONUMS
- jmp in_list
- ENDP float_p
-
- ;************************************************************************
- ;* Test for (integer? obj) *
- ;************************************************************************
- PROC integr_p
- mov dx, FIXNUMS or BIGNUMS
- jmp in_list
- ENDP integr_p
-
- ;************************************************************************
- ;* Test for (number? obj) *
- ;************************************************************************
- PROC number_p
- mov dx, NUMBERS
- jmp in_list
- ENDP number_p
-
- ;************************************************************************
- ;* Test for (pair? obj) *
- ;************************************************************************
- PROC pair_p
- mov dx, LISTCELL
- in_list:
- get1op
- mov bx, ax ; copy register number
- mov di, [regs+bx.page] ; load page number and
- attr_test:
- mov ax, [attrib+di]
- and ax, dx ; test against mask
- jnz attr_true
- attr_false:
- mov [regs+bx.page], 0 ; return ()
- mov [regs+bx.disp], 0
- jmp next
- attr_true:
- mov [regs+bx.bpage], T_PAGE*2
- mov [regs+bx.disp], T_DISP
- jmp next
- ENDP pair_p
-
- ;************************************************************************
- ;* Test for (port? obj) *
- ;************************************************************************
- PROC port_p
- mov dx, PORTS
- get1op
- mov bx, ax
- mov di, [regs+bx.page]
- cmp di, [console_reg.page] ; is it same page as 'console?
- jne attr_test
- mov ax, [regs+bx.disp]
- cmp ax, [console_reg.disp]
- je attr_true
- jmp attr_false
- ENDP port_p
-
- ;************************************************************************
- ;* Test for (proc? obj) *
- ;************************************************************************
- PROC proc_p
- mov dx, CONTINU or CLOSURE
- jmp in_list
- ENDP proc_p
-
- ;************************************************************************
- ;* Test for (inline? obj) *
- ;************************************************************************
- PROC inline_p
- mov dx, I86CODE
- jmp in_list
- ENDP inline_p
-
- ;************************************************************************
- ;* Test for (string? obj) *
- ;************************************************************************
- PROC string_p
- mov dx, STRINGS
- jmp in_list
- ENDP string_p
-
- ;************************************************************************
- ;* Test for (symbol? obj) *
- ;************************************************************************
- PROC symbol_p
- mov dx, SYMBOLS
- jmp in_list
- ENDP symbol_p
-
- ;************************************************************************
- ;* Test for (vector? obj) *
- ;************************************************************************
- PROC vector_p
- mov dx, VECTORS
- jmp in_list
- ENDP vector_p
-
- ;************************************************************************
- ;* is an integer even? even? dest *
- ;* *
- ;* Purpose: Scheme interpreter support for the even? predicate. *
- ;************************************************************************
- PROC even_p
- lea dx, [@@msg]
- DATASEG
- @@msg DB "EVEN?", 0
- CODESEG
- call eo_which ; is value even or odd?
- jnz in_odd_p
- in_even_p:
- mov [(REG bx).bpage], T_PAGE*2
- mov [(REG bx).disp], T_DISP
- save <si>
- jmp next_pc ; reload es, as we loadpage'd
- ENDP even_p
-
- ;************************************************************************
- ;* is an integer odd? odd? dest *
- ;* *
- ;* Purpose: Scheme interpreter support for the odd? predicate. *
- ;************************************************************************
- PROC odd_p
- lea dx, [@@msg]
- DATASEG
- @@msg DB "ODD?", 0
- CODESEG
- call eo_which ; is value even or odd?
- jnz in_even_p
- in_odd_p:
- xor ax, ax
- mov [(REG bx).bpage], al
- mov [(REG bx).disp], ax
- save <si>
- jmp next_pc ; reload es, as we loadpage'd
- ENDP odd_p
-
- JEQ_OPCODE = 01110100b
- JNE_OPCODE = 01110101b
- JLT_OPCODE = 01111100b
- JGE_OPCODE = 01111101b
- JLE_OPCODE = 01111110b
- JGT_OPCODE = 01111111b
-
- ;************************************************************************
- ;* Test for numeric inequality (!= n1 n2) *
- ;************************************************************************
- PROC ne_p
- mov dx, NE_OP
- mov [cs:cond_jmp], JNE_OPCODE
- jmp cond_go
- ENDP ne_p
-
- ;************************************************************************
- ;* Test for numeric less than (< n1 n2) *
- ;************************************************************************
- PROC lt_p
- mov dx, LT_OP
- mov [cs:cond_jmp], JLT_OPCODE
- jmp cond_go
- ENDP lt_p
-
- ;************************************************************************
- ;* Test for numeric greater than (> n1 n2) *
- ;************************************************************************
- PROC gt_p
- mov dx, GT_OP
- mov [cs:cond_jmp], JGT_OPCODE
- jmp cond_go
- ENDP gt_p
-
- ;************************************************************************
- ;* Test for numeric less than or equal (<= n1 n2) *
- ;************************************************************************
- PROC le_p
- mov dx, LE_OP
- mov [cs:cond_jmp], JLE_OPCODE
- jmp cond_go
- ENDP le_p
-
- ;************************************************************************
- ;* Test for numeric greater than or equal (>= n1 n2) *
- ;************************************************************************
- PROC ge_p
- mov dx, GE_OP
- mov [cs:cond_jmp], JGE_OPCODE
- jmp cond_go
- ENDP ge_p
-
- ;************************************************************************
- ;* Test for numeric equality (= n1 n2) *
- ;************************************************************************
- PROC eq_n
- mov dx, EQ_OP
- mov [cs:cond_jmp], JEQ_OPCODE
- jmp cond_go
- ENDP eq_n
-
- ;************************************************************************
- ;* Global definition - Support for arithmetic testing (cond n1 n2) *
- ;************************************************************************
- PROC cond_go
- get2op
- mov bl, al ; copy n1 register number
- lea di, [regs+bx]
- mov bl, ah ; copy n2 register number
- add bx, OFFSET regs
- cmp [(REG di).bpage], SPECFIX*2
- jne @@ool
- cmp [(REG bx).bpage], SPECFIX*2
- jne @@ool
- mov ax, [(REG bx).disp]
- cmp [(REG di).disp], ax
- LABEL cond_jmp BYTE
- jmp SHORT @@true
- @@false:
- xor ax, ax
- mov [(REG di).bpage], al
- mov [(REG di).disp], ax
- jmp next
- @@true:
- mov [(REG di).bpage], T_PAGE*2
- mov [(REG di).disp], T_DISP
- jmp next
-
- @@ool:
- push es ; saves es over C call
- call arith2 C, dx, di, bx ; Call the arithmetic processor
- pop es
- or ax, ax ; test result returned from arith2
- jg @@true
- jz @@false
- jmp sch_err
- ENDP cond_go
-
- ;************************************************************************
- ; Test for equality to zero (zero? n) *
- ;************************************************************************
- PROC eq_z_p
- mov dx, ZERO_OP
- mov [cs:cond0_jmp], JEQ_OPCODE
- jmp cond0_go
- ENDP eq_z_p
-
- ;************************************************************************
- ;* Test for less than zero (negative? n) *
- ;************************************************************************
- PROC lt_z_p
- mov dx, NEG_OP
- mov [cs:cond0_jmp], JLT_OPCODE
- jmp cond0_go
- ENDP lt_z_p
-
- ;************************************************************************
- ;* Test for greater than zero (positive? n) *
- ;************************************************************************
- PROC gt_z_p
- mov dx, POS_OP
- mov [cs:cond0_jmp], JGT_OPCODE
- jmp cond0_go
- ENDP gt_z_p
-
- ;************************************************************************
- ;* Global definition - Support for arithmetic testing (cond:0 n) *
- ;************************************************************************
- PROC cond0_go
- get1op
- mov bx, ax
- add bx, OFFSET regs
- cmp [(REG bx).bpage], SPECFIX*2
- jne @@ool
- cmp [(REG bx).disp], 0
- LABEL cond0_jmp BYTE
- jmp SHORT @@true
- @@false:
- xor ax, ax
- mov [(REG bx).bpage], al
- mov [(REG bx).disp], ax
- jmp next
- @@true:
- mov [(REG bx).bpage], T_PAGE*2
- mov [(REG bx).disp], T_DISP
- jmp next
-
- @@ool:
- push bx es ; saves es over C call
- call arith1 C, dx, bx
- pop es bx
- or ax, ax
- jg @@true
- jz @@false
- jmp sch_err
- ENDP cond0_go
-
- ;************************************************************************
- ;* (ascii->char n) ascii->char dest*
- ;* *
- ;* Purpose: Scheme interpreter support for the ascii->char function.*
- ;************************************************************************
- PROC asc_char
- get1op
- xchg ax, bx
- lea di, [regs+bx]
- cmp [(REG di).bpage], SPECFIX*2
- jne @@error
- and [(REG di).disp], 00ffh
- mov [(REG di).bpage], SPECCHAR*2 ; convert to character
- jmp next
- @@error:
- lea bx, [@@msg]
- DATASEG
- @@msg DB "INTEGER->CHAR", 0
- CODESEG
- jmp char_error
- ENDP asc_char
-
- ;************************************************************************
- ;* (char->ascii n) char->ascii dest*
- ;* *
- ;* Purpose: Scheme interpreter support for the char->ascii function.*
- ;************************************************************************
- PROC char_asc
- get1op
- xchg ax, bx
- lea di, [regs+bx]
- cmp [(REG di).bpage], SPECCHAR*2
- jne @@error
- mov [(REG di).bpage], SPECFIX*2
- jmp next
- @@error:
- lea bx, [@@msg]
- DATASEG
- @@msg DB "CHAR->INTEGER", 0
- CODESEG
- char_error:
- mov ax, 1
- call set_src_error C, bx, ax, di
- jmp sch_err
- ENDP char_asc
-
- ;************************************************************************
- ;* Support for list length (length list) *
- ;************************************************************************
- PROC slength
- get1op
- mov bx, ax
- save <si> ; save the program counter
- lea di, [regs+bx] ; load the address of the dest reg
- mov bx, [(REG di).page]
- mov si, [(REG di).disp]
- xor ax, ax ; zero the counter (32-bits)
- cwd
- @@loop:
- cmp bl, NIL_PAGE*2 ; pointer to nil?
- je @@done
- cmp [ptype+bx], LISTTYPE
- je @@typeok
-
- lea bx, [@@msg]
- DATASEG
- @@msg DB "LENGTH", 0
- CODESEG
- mov ax, 1
- call set_src_error C, bx, ax, di
- jmp sch_err
- @@typeok:
- add ax, 1 ; increment list cell count
- adc dx, 0
- ldpage es, bx
- mov bl, [(LISTDEF es:si).cdr.page]
- mov si, [(LISTDEF es:si).cdr.disp]
- cmp [s_break], 0 ; has the shift-break key been depressed?
- je @@loop
- in_slength:
- mov ax, 2 ; load instruction length = 2
- call restart C, ax ; link to Scheme debugger
- @@done:
- call long2int C, di, ax, dx
- jmp next_pc
- ENDP slength
-
- ;************************************************************************
- ;* Support for Last-pair (last-pair list) *
- ;************************************************************************
- PROC lst_pair
- get1op
- save <si>
- mov di, ax
- mov bx, [regs+di.page]
- cmp bl, NIL_PAGE*2 ; null pointer?
- je @@exit
- cmp [ptype+bx], LISTTYPE
- jne @@exit
- mov si, [regs+di.disp]
- xor dx, dx
- @@loop:
- ldpage es, bx
- mov dl, [(LISTDEF es:si).cdr.page]
- cmp dl, NIL_PAGE*2
- je @@done
- mov di, dx ; copy cdr's page number
- cmp [ptype+di], LISTTYPE
- jne @@done
- mov bl, dl ; follow linked list
- mov si, [(LISTDEF es:si).cdr.disp]
- cmp [s_break], 0 ; has the shift-break key been depressed?
- je @@loop
- jmp in_slength
- @@done:
- mov di, ax ; re-load destination register number
- mov [regs+di.bpage], bl
- mov [regs+di.disp], si
- @@exit:
- jmp next_pc
- ENDP lst_pair
-
- ;************************************************************************
- ;* (reverse! list) reverse! dest *
- ;* *
- ;* Purpose: Scheme interpreter support for the reverse! primitive *
- ;* *
- ;* Notes: The following registers are used by this routine: *
- ;* bl - page number of the current list cell *
- ;* di - displacement of the current list cell *
- ;* es - paragraph address of the current list cell *
- ;* Note: es:[di] address the current list cell *
- ;* dl - page number of the previous list cell *
- ;* ax - displacement of the previous list cell *
- ;* si - destination register number *
- ;************************************************************************
- PROC reverseb
- get1op
- save <si>
- mov bl, al
- lea si, [regs+bx]
- mov bl, [(REG si).bpage]
- mov di, [(REG si).disp]
- cmp [ptype+bx], LISTTYPE ; first element has to be a pair
- jne @@error
- push bx di ; save resulting last-pair
- xor ax, ax
- xor dx, dx
- @@loop:
- cmp bl, NIL_PAGE*2 ; end of list (current cell nil)?
- je @@done
- ldpage es, bx
- xchg [(LISTDEF es:di).cdr.page], dl ; swap cdr field with previous cell
- xchg [(LISTDEF es:di).cdr.disp], ax ; pointer
- xchg bx, dx ; current cell <-> (cdr current cell)
- xchg di, ax
- cmp [ptype+bx], LISTTYPE ; dotted list ?
- je @@loop ;
- mov cx, di ; special handling of dotted lists
- mov dh, bl ; used to implement LIST?
- pop di bx ; (reverse! behavior is only specified
- ldpage es, bx ; for proper lists)
- mov [(LISTDEF es:di).cdr.page], dh ; put cdr of dotted pair at
- mov [(LISTDEF es:di).cdr.disp], cx ; dotted end of reversed list
- push bx di
- @@done:
- pop di bx
- mov [(REG si).bpage], dl ; make destination register point
- mov [(REG si).disp], ax ; to new head of (reversed) list
- jmp next_pc
- @@error:
- mov [(REG si).bpage], dl
- mov [(REG si).disp], ax
- lea bx, [@@msg]
- DATASEG
- @@msg DB "REVERSE!", 0
- CODESEG
- jmp src_err
- ENDP reverseb
-
- ;************************************************************************
- ;* Mouse support *
- ;************************************************************************
- PROC smouse NEAR
- or [mouse_use], 1
- get1op
- mov [save_ax], ax
- mov cx, ax ; used by @@pushint
- call @@pushint
- mov [save_bx], bx ; save 1st register
- call @@pushint
- call @@pushint
- call @@pushint
- pop dx
- call @@pushint
- call @@pushint ; stack contains DI, SI, CX, BX, AX
- cmp [BYTE save_ax], 7
- jne @@6args
- call get1parm
- mov bx, ax
- cmp [(REG bx).bpage], NIL_PAGE*2
- jne @@string
- push cs
- pop es
- lea dx, [cs:mouse_handler]
- jmp @@6args
- @@string:
- mov dx, [(REG bx).disp]
- mov bx, [(REG bx).page]
- ldpage es, bx
- add dx, OFFSET (TYPE STRDEF).buffer
- @@6args:
- pop di
- pop si
- pop cx
- pop bx
- pop ax
- or ax, ax
- jb @@special
- int 33h
- @@return:
- push ax
- push bx
- push cx
- push dx
- mov [tmp_reg.bpage], SPECFIX*2
- mov [save_cx], 4
- lea bx, [nil_reg]
- @@loop:
- pop [tmp_reg.disp]
- call cons C, [save_bx], [tmp_adr], bx
- mov bx, [save_bx]
- dec [save_cx]
- jnz @@loop
- jmp next_pc
-
- @@special:
- mov [mouse_use], bx ; set first use flag
- jmp @@return
-
- @@pushint:
- pop di ; get return address
- jcxz @@outofargs
- dec cx
- call get1parm
- mov bx, ax
- push [(REG bx).disp]
- jmp di
- @@outofargs:
- xor ax, ax
- push ax
- jmp di
- ENDP smouse
-
- ;************************************************************************
- ;* Interface to Varargs (%graphics/mouse/esc len arg1 ... argn) *
- ;* *
- ;* completely revised 930929 LB *
- ;* completely revised 3/6/92 LB - modified 15/6/92 MV *
- ;* now len=n is the number of optional arguments, *
- ;* arg1 is the subfunction number *
- ;* and arg2..argn have any type you wish *
- ;* arg1 will be used to hold the result *
- ;************************************************************************
- PROC sgraph
- lea bx, [@@msg]
- lea di, [@@link]
- jmp varargs
- DATASEG
- @@link DD graphit
- @@msg DB "%GRAPHICS", 0
- CODESEG
- ENDP sgraph
-
- PROC s_esc
- lea bx, [@@msg]
- lea di, [@@link]
- jmp varargs
- DATASEG
- @@link DD asm_link
- @@msg DB "%ESC", 0
- CODESEG
- ENDP s_esc
-
- PROC varargs
- push bx ; save message's address
- get1op
- mov cx, ax
- mov bx, ax
- @@loop:
- get1op
- mov ah, 0
- add ax, OFFSET regs
- push ax
- loop @@loop
- save <si>
- push bx ; pass number of args to routine
- call [DWORD di] C
- pop bx ; graphit SHOULD NOT modify arg count
- shl bx, 1
- add sp, bx
- pop bx ; restore message
- or ax, ax
- jnz @@error
- jmp next_pc
- @@error:
- jmp src_err
- ENDP varargs
-
- ;************************************************************************
- ;* Error routines *
- ;************************************************************************
-
- ;************************************************************************
- ;* Timer Ran Down *
- ;************************************************************************
- ; Note: the "reset_timer" variable must be in the code segment 'cause
- ; there's no telling where the ds register points when a
- ; timer interrupt occurs.
-
- reset_timer DW 0 ; save area for resetting a timer int
- PROC timeout
- mov ax, [cs:reset_timer]
- mov [cs:$$sm$entry], ax ; branch at top of vm loop
- call rsttimer C ; turn off the timer support
- mov bx, TIMEOUT_CONDITION ; load "timeout" error code
- in_timer_restart:
- xor ax, ax ; set code for "restartable" operation
- lea cx, [nil_reg] ; set *irritant* to 'nil
- in_timer_setnumerr:
- push es ; saves es over C call
- call set_numeric_error C, ax, bx, cx
- pop es
- jmp sch_err
- ENDP timeout
-
- ;************************************************************************
- ;* Mouse Event occured *
- ;************************************************************************
- reset_mouse DW 0
- PROC mouseevent
- push si ; we must keep the VM IP counter
- mov ax, [cs:reset_mouse]
- mov [cs:$$sm$entry], ax ; branch at top of vm loop
- lea si, [mstate]
- lea cx, [nil_reg] ; set *irritant* to 'mouse params'
- @@loop:
- call mputevent C
- call cons C, [tmp_adr], [tm2_adr], cx
- lea cx, [tmp_reg]
- add si, SIZE MOUSESTATE
- cmp si, [mstptr]
- jb @@loop
- mov [mstptr], OFFSET mstate
-
- mov bx, TIMEOUT_CONDITION ; load "mouse" error code
- xor ax, ax ; set code for "restartable" operation
- pop si
- jmp in_timer_setnumerr
-
- PROC mputevent C
- LOCAL @@reg:REG, @@ptr:WORD
- lea ax, [@@reg]
- mov [@@ptr], ax
- call long2int C, ax, [WORD LOW (MOUSESTATE si).time], [WORD HIGH (MOUSESTATE si).time]
- lea ax, [nil_reg]
- call cons C, [tm2_adr], [@@ptr], ax
- lea di, [(MOUSESTATE si).y_mickeys] ; last arg
- mov [@@reg.bpage], SPECFIX*2 ; and enqueue the event
- @@args:
- mov ax, [di]
- mov [@@reg.disp], ax
- call cons C, [tm2_adr], [@@ptr], [tm2_adr]
- dec di
- dec di
- cmp di, si
- jae @@args
- ret
- ENDP
- ENDP mouseevent
-
- ;************************************************************************
- ;* Shift-Break Interrupt *
- ;************************************************************************
- PROC sc_debug
- mov ax, [cs:reset_sb] ; reset forced branch at top of VM loop
- mov [cs:$$sm$entry], ax
- mov [s_break], 0 ; reset shift-break flag
- mov bx, SHIFT_BREAK_CONDITION ; load "shift-break" error code
- jmp in_timer_restart
- ENDP sc_debug
-
- ;************************************************************************
- ;* Recover stack macro *
- ;************************************************************************
- MACRO CLEANUP_STACK
- push ax bx cx dx es ; preserve main registers
- mov ax, [reset_bp] ; compute new stack limits
- sub ax, LCLSIZE+USESSIZE
- call @REG@cleanup$qp3REGt1 C, sp, ax
- pop es dx cx bx ax
- mov bp, [reset_bp] ; clean up stack
- lea sp, [bp-LCLSIZE-USESSIZE]
- ENDM
-
- ;************************************************************************
- ;* DOS fatal I/O error process *
- ;************************************************************************
- PROC dos_error FAR
- add sp, 4 ; dump return address
- pop ax ; restart/non-restart flag
- pop bx ; error code
- pop cx ; *irritant*
- CLEANUP_STACK
- jmp in_timer_setnumerr ; go invoke Scheme debugger
- ENDP dos_error
-
- ;************************************************************************
- ;* Error-- Undefined Opcode *
- ;************************************************************************
- PROC not_op
- dec si ; back up location pointer
- save <si> ; and save it
- lea bx, [@@msg]
- mov [tmp_reg.bpage], SPECFIX*2; convert opcode to a fixnum
- mov [tmp_reg.disp], ax ; representation for use as "irritant"
- lea ax, [tmp_reg]
- jmp in_recompil_error
- DATASEG
- @@msg DB "[VM INTERNAL ERROR] Undefined opcode", LF, 0
- CODESEG
- ENDP not_op
-
- ;************************************************************************
- ;* Error-- Invalid Source Operand *
- ;************************************************************************
- ; Note: at this point, bx contains the address for text of failing inst.
- PROC src_err
- xor ax, ax
- call set_src_error C, bx, ax
- jmp sch_err ; link to Scheme debugger
- ENDP
-
- ;************************************************************************
- ;* Error-- Object Module Not Compatible With Current Revision Level *
- ;************************************************************************
- PROC recompil
- lea ax, [nil_reg]
- lea bx, [@@msg]
- in_recompil_error:
- mov cx, 1
- call set_error C, cx, bx, ax ; set the error parameters
- jmp sch_err ; link to Scheme debugger
- DATASEG
- @@msg DB "[VM ERROR encountered!] Object module incompatible with this Version", LF
- DB "Recompile from Source", LF, 0
- CODESEG
- ENDP recompil
-
- ;************************************************************************
- ;* Error: Feature Not Yet Implemented *
- ;************************************************************************
- PROC not_yet
- lea bx, [@@msg]
- dec si ; back up location pointer
- push es ; saves es over C call
- call zprintf C, bx ; call zprintf
- pop es
- mov ax, RV_CLOBBERED
- jmp in_debug
- DATASEG
- @@msg DB "[VM INTERNAL ERROR] Feature not implemented", LF, 0
- CODESEG
- ENDP not_yet
-
- ;************************************************************************
- ;* Force Restart of Current Operation *
- ;************************************************************************
- PROC C restart FAR @@inlength:WORD
- mov ax, [@@inlength]
- CLEANUP_STACK
- sub [save_si], ax ; back up the instruction pointer
- jmp next_pc
- ENDP restart
-
- ;************************************************************************
- ;* Go to error handling code from C *
- ;************************************************************************
- PROC C scheme_error FAR
- CLEANUP_STACK
- ; jmp sch_err ; fall through
- ENDP scheme_error
-
- ;************************************************************************
- ;* Link to the Scheme Debugger *
- ;************************************************************************
- PROC sch_err
- call force_call C, si ; force a new stack frame to be built
- mov bx, SPECCODE*2 ; load code base pointer for debug init
- mov [cb_reg.bpage], bl
- mov [cb_reg.disp], 0
- ldpage es, bx
- mov si, [err_ent] ; load error entry point offset
- cld
- jmp next
- ENDP sch_err
-
- ;************************************************************************
- ;* Scheme-Reset/Reset *
- ;* *
- ;* Purpose: To re-initialize the VM's environment to correct for *
- ;* some error condition *
- ;************************************************************************
- PROC force_reset FAR
- CLEANUP_STACK
- ; jmp s_reset ; falls through
- ENDP force_reset
-
- PROC s_reset
- push es ; saves es over C call
- call scheme_reset C ; Adjust fluid environment
- pop es
- ; jmp reset ; falls through
- ENDP s_reset
-
- PROC reset
- push es ; saves es over C call
- call reset_fasl C ; reset %fasl input data structures
- pop es
- xor ax, ax ; create a value of zero/nil
- mov [prev_reg.page], ax ; previous stack segment <- nil
- mov [prev_reg.disp], ax
- mov [cb_reg.disp], ax ; current code base <- loader's code page
- mov [cb_reg.page], SPECCODE*2
- mov [base], ax ; reset stack
- mov [frameptr], ax
- mov [topofstack], SIZE STKFDEF-SIZE POINTER
- mov bx, SPECCODE*2 ; set the location pointer and code paragraph address
- ldpage es, bx
- mov si, [rst_ent] ; load the new location pointer
- ; jmp clr_regs ; falls through
- ENDP reset
-
- ;************************************************************************
- ;* Clear VM registers clear-regs *
- ;************************************************************************
- PROC clr_regs
- push es
- push ds ; make es point to ds
- pop es
- xor ax, ax
- mov [tmp_reg.disp], ax ; clear the VM's temporary register, too
- mov [tmp_reg.page], ax
- mov [tm2_reg.disp], ax ; clear the VM's temporary register, too
- mov [tm2_reg.page], ax
- lea di, [regs] ; store #!false into R0 and R1
- mov cx, 4
- rep stosw
-
- mov bx, UN_DISP ; load pointer for "unbound" symbol
- mov dx, UN_PAGE*2
- mov cx, NUM_REGS-2 ; load iteration count
- @@loop:
- mov ax, bx ; copy '**unbound** displacement pointer
- stosw
- mov ax, dx ; do likewise for the page number component
- stosw
- loop @@loop
-
- pop es
- jmp next
- ENDP clr_regs
-
- ;************************************************************************
- ;* (%str-append str1 start1 end1 {nil,char,str2} str3 start3 end3) *
- ;************************************************************************
- PROC s_append
- mov cx, 7 ; load count of number of operands
- @@pushargs:
- xor ax, ax ; clear ah
- get1op
- add ax, OFFSET regs ; compute the register's address
- push ax ; save the register's address on the stack
- loop @@pushargs
- save <si>
- call str_apnd C ; FAR call to substring-append support
- or ax, ax ; success ?
- jnz @@error
- add sp, 2*7 ; if yes, pop off arguments from stack
- jmp next_pc
- @@error:
- lea ax, [@@msg] ; else send standard error message
- mov cx, 7
- call set_src_error C, ax, cx ; ADD these arguments to the 7 other
- add sp, 2*7 ; pop off arguments
- in_append_error:
- jmp sch_err
- DATASEG
- @@msg DB "%STRING-APPEND", 0
- CODESEG
- ENDP s_append
-
- ;************************************************************************
- ;* (%substring-display str start end row-displacement window) *
- ;************************************************************************
- PROC s_disply
- mov cx, 5
- @@pushargs:
- xor ax, ax
- get1op
- add ax, OFFSET regs
- push ax
- loop @@pushargs
- save <si>
- call str_disp C
- add sp, 2*5
- or ax, ax ; did an error occur ?
- jnz in_append_error
- jmp next_pc
- ENDP s_disply
-
- ;************************************************************************
- ;* Invoke garbage collection gc *
- ;************************************************************************
- PROC gc
- save <si>
- xor ax, ax ; assume CX = NILPAGE*2 = NILDISP
- mov [tmp_reg.page], ax ; clear tmp_reg.rreg prior to GC
- mov [tmp_reg.disp], ax
- mov [tm2_reg.page], ax ; clear tm2_reg.rreg prior to GC
- mov [tm2_reg.disp], ax
- call garbage C ; call garbage collection driver
- jmp next_pc
- ENDP gc
-
- ;************************************************************************
- ;* Invoke garbage collection with compaction gc2 *
- ;************************************************************************
- PROC sgc2
- save <si>
- xor ax, ax ; assume CX = NILPAGE*2 = NILDISP
- mov [tmp_reg.page], ax ; clear tmp_reg.rreg prior to GC
- mov [tmp_reg.disp], ax
- mov [tm2_reg.page], ax ; clear tm2_reg.rreg prior to GC
- mov [tm2_reg.disp], ax
- call garbage C ; call garbage collection driver
- call gcsquish C
- jmp next_pc
- ENDP sgc2
-
- ;************************************************************************
- ;* Begin Debug %begin-debug *
- ;************************************************************************
- PROC debug_op
- mov [vm_debug], 1 ; enable VM debugger for (%begin-debug)
- mov ax, RV_SDEBUG
- in_debug:
- IFDEF VMDEBUG
- mov bx, [cs:$$sm$trace] ; modify interpreter to enable instr.
- mov [cs:$$sm$entry], bx
- mov [s_break], 0 ; reset shift-break flag
- ENDIF
- jmp in_exit
- ENDP debug_op
-
- ;************************************************************************
- ;* Exit interpreter *
- ;************************************************************************
- PROC exit_op
- get1op
- add ax, OFFSET regs
- mov bx, ax
- xor ax, ax
- cmp [(REG bx).bpage], SPECFIX*2
- jne @@notfix
- mov ax, [(REG bx).disp]
- @@notfix:
- mov bx, [$$retcode]
- mov [bx], ax
- sub si, 2 ; back up PC to avoid falling past end
- mov ax, RV_HALT
- in_exit:
- mov bx, [$$entry]
- mov [bx], si
- ; jmp end_interp ; fall through
- ENDP exit_op
-
- end_interp:
- ret
-
- ENDP interp
- END
-